Git 工作原理睡蟋,基本操作踏幻,創(chuàng)建與合并分支

前東家使用 Perforce 做版本控制,現(xiàn)東家使用 Git戳杀。

Git 工作原理

Git 和其他版本控制系統(tǒng)的主要差別在于该面,Git 只關心文件數(shù)據(jù)的整體是否發(fā)生變化夭苗,而大多數(shù)其他系統(tǒng)則只關心文件內容的具體差異。
這類系統(tǒng)(CVS隔缀,Subversion题造,Perforce,Bazaar 等等)每次記錄有哪些文件作了更新猾瘸,以及都更新了哪些行的什么內容:


其他系統(tǒng)在每個版本中記錄著各個文化的具體差異

Git 并不保存這些前后變化的差異數(shù)據(jù)界赔。實際上,Git 更像是把變化的文件作快照后牵触,記錄在一個微型的文件系統(tǒng)中淮悼。每次提交更新時,它會縱覽一遍所有文件的指紋信息并對文件作一快照揽思,然后保存一個指向這次快照的索引袜腥。為提高性能,若文件沒有變化钉汗,Git 不會再次保存羹令,而只對上次保存的快照作一鏈接。Git 的工作方式就如下圖所示:


Git保存每次更新時的文件快照

工作區(qū) Working Directory VS 暫存區(qū) Staging Directory

Git 工作流

本地倉庫由 Git 維護的三棵“樹“組成:

  • 工作目錄 Working Directory损痰,它持有實際文件
    例如福侈,我們添加了一個文件 NewFile.txt,那它就是在工作目錄 Working Directory 中:

    工作目錄 Working Directory

  • 暫存區(qū) Staging Directory 或者叫 Index Directory卢未,緩存區(qū)域癌刽,臨時保存文件的改動
    我們通過 git add 命令添加到暫存區(qū) Staging Directory 或者叫 Index Directory:

    暫存區(qū) Staging Directory 或者叫 Index Directory

  • 倉庫 Head 區(qū),指向最后一次提交的結果
    我們通過 git commit 命令實際提交改動到 Head 區(qū):

    image.png

通過下面這個圖可以清晰的表示不同區(qū)的切換:
引用自:http://marklodato.github.io/visual-git-guide/index-zh-cn.html

不同區(qū)的切換

文件的三種狀態(tài)

  • 已修改 (modified):表示修改了某個文件尝丐,但還沒有提交保存
  • 已暫存 (staged):表示把已修改的文件放在下次提交時要保存的清單中
  • 已提交 (committed):表示該文件已經(jīng)被安全的保存在本地數(shù)據(jù)庫中了

版本庫

工作區(qū)中的隱藏目錄 .git,就是 Git 的版本庫衡奥。
.git 目錄結構如下:

.git 目錄結構

其中:

  • HEAD 文件:指示目前被檢出的分支

    HEAD 文件

  • index文件:保存暫存區(qū)信息

  • objects 目錄:存儲所有數(shù)據(jù)內容

    objects 目錄

  • refs 目錄:存儲指向數(shù)據(jù)(分支)的提交對象的指針

    refs 目錄

什么是 HEAD

HEAD 默認指向指向當前分支的最新提交爹袁。


HEAD 默認指向指向當前分支的最新提交

也可以通過 git show HEAD 命令看到當前 HEAD 的位置:

通過 git show HEAD 命令看到當前 HEAD 的位置

  • HEAD 可以指向某個分支,如果指向某個分支矮固,則永遠指向分支上的最新提交
  • 當然 HEAD 也可以指向某個提交

什么是 origin 和 master

通過 Git 來修改代碼失息,主要包括如下三步:

  • 從 Git 取數(shù)據(jù) git clone
    • 涉及到 遠程服務器下的某個倉庫下的某個分支 remote server/remote repository/remote branch
  • 改動代碼
    • 涉及到 本地某個倉庫下的某個分支 local repository/local branch
  • 將改動傳回 Git git push
    • 涉及到 遠程服務器下的某個倉庫下的某個分支 remote server/remote repository/remote branch

涉及到兩個 repository:

  • 遠程倉庫 Remote Repository,在遠程服務器上
  • 本地倉庫 Local Repository档址,在本地工作區(qū)上

找到最近創(chuàng)建的一個 Github 項目:https://github.com/chenxiangcyr/spring-cloud-config-repo-demo
現(xiàn)在我們通過如下命令 Clone 到本地:
git clone git@github.com:chenxiangcyr/spring-cloud-config-repo-demo.git

在 Clone 完成之后盹兢,Git 會自動為你將此遠程倉庫命名為 origin,并下載其中所有的數(shù)據(jù)守伸,建立一個指向它的 master 分支的指針绎秒。
因此 origin 是遠程倉庫的名字,master 是分支的名字尼摹。
我們用 (遠程倉庫名)/(分支名) 這樣的形式表示遠程分支见芹,所以 origin/master 指向的是一個遠程分支 remote branch剂娄。我們實際上是從這個遠程分支 remote branch 中 Clone 數(shù)據(jù)到本地,但你無法在本地更改遠程分支 remote branch 中的數(shù)據(jù)玄呛。
通過 git branch -r 可以查看遠程分支:

查看遠程分支

我們也可以通過 cat .git/config 看到 origin 的含義:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[remote "origin"]
    url = git@github.com:chenxiangcyr/spring-cloud-config-repo-demo.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
    remote = origin
    merge = refs/heads/master

同時阅懦,Git 會建立一個屬于你自己的本地 master 分支,它指向的是你剛剛從遠程分支 remote branch 傳到你本地的副本徘铝。
通過 git branch 可以查看本地分支:

本地分支

總結:

  • master 就是本地分支 local branch
  • origin/master 是遠程分支 remote branch
  • remotes/origin/masterorigin/master 的指向是相同的
  • 我們可以通過 git diff origin/master master 來顯示 本地分支 與 遠程分支 的區(qū)別

隨著你不斷的改動文件耳胎,git add, git commitmaster 的指向會自動移動惕它。最終你還要通過 git push 命令來將修改推送到遠程分支怕午。
git push origin master:master

  • 我們看到有兩個 master,其中前面一個為 source怠缸,后面一個為 destination
  • 該命令可以理解為诗轻,在本地倉庫中找到名字為 master 的分支,使用它去更新遠程倉庫下名字為 master 的分支揭北,如果遠程倉庫下不存在名字是 master 的分支扳炬,那么新建一個。
  • git push origin master (省略了<destination>搔体,等價于 git push origin master:master

Git 基本操作

引用自:http://marklodato.github.io/visual-git-guide/index-zh-cn.html


上面的四條命令在工作目錄恨樟、暫存目錄(也叫做索引)和倉庫之間復制文件。

  • git add files 把當前文件放入暫存區(qū)域疚俱。

  • git commit 給暫存區(qū)域生成快照并提交劝术。

  • git reset files 用來撤銷最后一次 git add files,你也可以用 git reset 撤銷所有暫存區(qū)域文件呆奕。
    例如我們修改了文件 NewFile.txt(添加了內容 123)养晋,通過 git add NewFile.txt 放入暫存區(qū)域,隨后通過 git reset NewFile.txt 來撤銷梁钾,但是修改的內容沒有被撤銷(依然是 123):

    git reset files 用來撤銷最后一次 git add files

  • git checkout files 把文件從暫存區(qū)域復制到工作目錄绳泉,用來丟棄本地修改。
    例如在上面的基礎上執(zhí)行 git checkout NewFile.txt姆泻,這時候 NewFile.txt 所修改的內容被撤銷了零酪。

    git checkout files 把文件從暫存區(qū)域復制到工作目錄,用來丟棄本地修改

也可以跳過暫存區(qū)域直接從倉庫取出文件或者直接提交代碼:


  • git commit -a相當于運行 git add 把所有當前目錄下的文件加入暫存區(qū)域再運行 git commit拇勃。
  • git commit files 進行一次包含最后一次提交加上工作目錄中文件快照的提交四苇,并且文件被添加到暫存區(qū)域。
  • git checkout HEAD files 從倉庫歷史中回滾到復制最后一次提交到工作區(qū)方咆。

diff 查看兩次提交之間的變動

  • git diff NexFile.txt 查看工作目錄與暫存區(qū)的變動
  • git diff HEAD NexFile.txt 查看工作目錄與倉庫中 HEAD 的變動
  • git diff --cached NexFile.txt 查看暫存區(qū)與倉庫中 HEAD 的變動
  • git diff <branch> NexFile.txt 查看工作目錄與倉庫中某個分支的變動
  • git diff <commit> <commit> 查看兩次 commit 之間的變動
    diff 查看兩次提交之間的變動

checkout

checkout 命令用于從歷史提交(或者暫存區(qū)域)中拷貝文件到工作目錄月腋,也可用于切換分支。

  • 當給定某個文件名(或者打開 -p 選項,或者文件名和 -p選項同時打開)時罗售,Git 會從指定的提交中拷貝文件到暫存區(qū)域和工作目錄辜窑。比如,git checkout HEAD NewFile.txt 會將提交節(jié)點 HEAD~ (即當前提交節(jié)點的父節(jié)點)中的 NewFile.txt 復制到工作目錄并且加到暫存區(qū)域中寨躁。
  • 當不指定文件名穆碎,而是給出一個(本地)分支時,那么 HEAD 標識會移動到那個分支(也就是說职恳,我們“切換”到那個分支了)所禀,然后暫存區(qū)域和工作目錄中的內容會和 HEAD 對應的提交節(jié)點一致。
  • 如果既沒有指定文件名放钦,也沒有指定分支名色徘,而是一個標簽、遠程分支操禀、SHA-1值或者是像 master~3 類似的東西褂策,就得到一個匿名分支,稱作 detached HEAD(被分離的HEAD標識)颓屑。

reset

reset 命令把當前分支指向另一個位置斤寂,并且有選擇的變動工作目錄和索引。也用來在從歷史倉庫中復制文件到索引揪惦,而不動工作目錄遍搞。

如果不給選項,那么當前分支指向到那個提交器腋。如果用 --hard 選項溪猿,那么工作目錄也更新,如果用 --soft選項纫塌,那么都不變诊县。
如果沒有給出提交點的版本號,那么默認用 HEAD措左。這樣翎冲,分支指向不變,但是索引會回滾到最后一次提交媳荒,如果用 --hard 選項,工作目錄也同樣驹饺。

reset

cherry pick

cherry-pick 命令"復制"一個提交節(jié)點并在當前分支做一次完全一樣的新提交钳枕。

cherry pick

rebase

交互式變基 (rebase)。它可以用來編輯提交信息赏壹,或者將多個提交壓縮成一個提交鱼炒。
git rebase -i HEAD~n

Git 創(chuàng)建與合并分支

Git 關于分支的操作主要包括:

  • 查看分支git branch
  • 創(chuàng)建分支git branch <name>
  • 切換分支git checkout <name>
  • 創(chuàng)建 + 切換分支git checkout -b <name>
  • 合并某分支到當前分支git merge <name>
  • 刪除分支git branch -d <name>

每次提交,Git 都把它們串成一條時間線蝌借,這條時間線就是一個分支昔瞧。在 Git 里指蚁,這個分支叫主分支,即 master 分支自晰。HEAD 嚴格來說不是指向提交凝化,而是指向 mastermaster 才是指向提交的酬荞,所以搓劫, HEAD 指向的就是當前分支。每次提交混巧,master 分支都會向前移動一步枪向,這樣,隨著你不斷提交咧党,master 分支的線也越來越長:

一個具體的 Case

我們目前在 master 分支上秘蛔,下一階段要開發(fā)一個新需求付款,因此需要在一個新的分支 payment 上開發(fā)傍衡,測試深员,最后合并到 master 分支上。

創(chuàng)建新分支:

git checkout -b payment

以上操作相當于:

git branch payment
git checkout payment

隨后我們在 payment 分支在不斷的向前推進:

這時候聪舒,突然來了一個線上的 Issue辨液,需求緊急修復,因此我們停下手動上的工作箱残,需要在一個新的分支 bugfix 上開發(fā)滔迈,測試,最后合并到 master 分支上被辑。

創(chuàng)建新分支:

git checkout -b bugfix

隨后我們在 bugfix 分支上進行修改:

測試沒問題后燎悍,合并到 master 分支上:

git checkout master
git merge bugfix

在合并的時候,由于當前 master 分支所指向的提交是 bugfix 的直接上游盼理,所以 Git 只是簡單的將指針向前移動谈山。 換句話說,當你試圖合并兩個分支時宏怔,如果順著一個分支走下去能夠到達另一個分支奏路,那么 Git 在合并兩者的時候,只會簡單的將指針向前推進(指針右移)臊诊,因為這種情況下的合并操作沒有需要解決的分歧鸽粉,這就叫做 “快進(fast-forward)”。

隨后我們上線該緊急修復抓艳,然后可以使用命令來刪除 bugfix 分支:

git branch -d bugfix

接下來触机,我們切換到之前的 payment 分支上繼續(xù)工作:

測試沒問題后,合并到 master 分支上:

git checkout master
git merge payment

這和你之前合并 bugfix 分支的時候看起來有一點不一樣。在這種情況下儡首,你的開發(fā)歷史從一個更早的地方開始分叉開來片任。 因為 master 分支所在提交并不是 payment 分支所在提交的直接祖先,Git 不得不做一些額外的工作蔬胯。

出現(xiàn)這種情況的時候对供,Git 會使用兩個分支的末端所指的快照(藍色部分)以及這兩個分支的工作祖先(黃色部分),做一個簡單的三方合并笔宿。


引用:
Git 教程 創(chuàng)建與合并分支
3.2 Git 分支 - 分支的新建與合并
淺析 Git 思想和工作原理
圖解Git
Git 的origin和master分析(轉)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末犁钟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子泼橘,更是在濱河造成了極大的恐慌涝动,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炬灭,死亡現(xiàn)場離奇詭異醋粟,居然都是意外死亡,警方通過查閱死者的電腦和手機重归,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門米愿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鼻吮,你說我怎么就攤上這事育苟。” “怎么了椎木?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵违柏,是天一觀的道長。 經(jīng)常有香客問我香椎,道長漱竖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任畜伐,我火速辦了婚禮馍惹,結果婚禮上,老公的妹妹穿的比我還像新娘玛界。我一直安慰自己万矾,他們只是感情好,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布慎框。 她就那樣靜靜地躺著勤众,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鲤脏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天,我揣著相機與錄音猎醇,去河邊找鬼窥突。 笑死,一個胖子當著我的面吹牛硫嘶,可吹牛的內容都是我干的阻问。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼沦疾,長吁一口氣:“原來是場噩夢啊……” “哼称近!你這毒婦竟也來了?” 一聲冷哼從身側響起哮塞,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤刨秆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后忆畅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衡未,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年家凯,在試婚紗的時候發(fā)現(xiàn)自己被綠了缓醋。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡绊诲,死狀恐怖送粱,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情掂之,我是刑警寧澤抗俄,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站板惑,受9級特大地震影響橄镜,放射性物質發(fā)生泄漏。R本人自食惡果不足惜冯乘,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一洽胶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧裆馒,春花似錦姊氓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至梗搅,卻和暖如春禾唁,著一層夾襖步出監(jiān)牢的瞬間制市,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工泳秀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留娜睛,地道東北人。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓掘托,卻偏偏與公主長得像瘦锹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子闪盔,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內容

  • 在 版本回退 里弯院,你已經(jīng)知道,每次提交泪掀,Git都把它們串成一條時間線听绳,這條時間線就是一個分支。截止到目前族淮,只有一條...
    sidney_c閱讀 298評論 0 0
  • Git 基礎 基本原理 客戶端并不是只提取最新版本的文件快照辫红,而是把代碼倉庫完整的鏡像下來。這樣一來祝辣,任何一處協(xié)同...
    __silhouette閱讀 15,880評論 5 147
  • 夏日伊始的思念 纏繞著太陽熾熱的光線 跨進南回歸線 落滿地的秋葉 層層疊疊 滿是回憶的積淀 晴天夜空的星星 是你寄...
    惠施chen閱讀 204評論 0 2
  • 總有一天你會和我遇見 像好友一樣卻失散多年 你一句我一句單純聊天 說你過的還不錯在以前 靚麗光鮮映入了我眼簾 講我...
    沈九壹閱讀 180評論 0 0
  • 又是一陣風雨來襲 而我獨往其中 別問我贴妻,我是誰 一場從未相遇的運 而你不曾遇見 而這不曾懷戀 而我失去了記憶 只是...
    念及我x閱讀 181評論 0 1