原文連接:CS Visualized: Useful Git Commands,by Lydia Hallie(有刪改)。css
本文會介紹一些經常使用 Git 指令的圖解說明。包括:git
git merge
)當項目中多條功能分支時,有時就須要使用 git merge
命令,指定將某個分支的提交合併到當前分支。Git 中有兩個合併策略:fast-forward 和 no-fast-forward。fetch
--ff
)若是當前分支,在合併分支前,沒有作過額外提交。那麼合併分支的過程不會產生的新的提交記錄,而是直接將分支上的提交添加進來。這稱爲 fast-forward 合併。 ui
如今dev
分支上的修改已所有合併到主分支
master
上。那 no-fast-forward 又是什麼呢?
--no-ff
)上面的場景不多遇到,基本是:在當前分支分離出子分支後,作了一些修改;而分離出的子分支也作了修改。這個時候再使用 git merge
,就會觸發 no-fast-forward 策略了。3d
在 no-fast-forward 策略下,Git 會在當前分支(active branch)額外建立一個新的 合併提交(merging commit)。這條提交記錄既指向當前分支,又指向合併分支。 日誌
合併後,在當前主分支 master 上包含 dev 分支上的全部修改。若是兩個分支的修改存在衝突:好比說同時修改了某個文件的同一行;或者一個分支刪除了文件,另外一個分支則修改了文件——對於這種狀況,Git 是沒法自行決定合併策略的。這個時候,Git 就會把合併操做交給咱們。code
舉個例子,兩個分支對同一個 README.md
文件作了修改。cdn
若是此時將 dev
合併到 master
,那麼就存在合併衝突了:標題是使用 Hello!
仍是 Hey!
呢?blog
當在主分支上執行 git merge
後,Git 會提示存在合併衝突,並把衝突的地方標記出來。咱們手工處理完畢後,保存修改、添加文件、而後提交修改就能夠了。 開發
git rebase
)除了 git merge
,還能使用 git rebase
來合併分支。git rebase
指令會 複製 當前分支的全部最新提交,而後將這些提交添加到指定分支提交記錄之上。
如圖,dev
分支是從主分支上分離出去的(在 i8fe5
處),以後主分支與 dev
分支上都有相應的修改。執行 git rebase master
指令後,dev
分支將本身的最新提交記錄複製出來(提交 hash 也發生了改變),拼在了主分支最後一次提交之上。這種合併分支的方式,會另 Git 提交歷史看起來很清爽。
變基在開發功能(feature branch)分支時頗有用——在開發功能時,主分支上可能也作了一些更新,咱們能夠將主分支上的最新更新經過變基合併到功能分支上來,這在將來在主分支上合併功能分支避免了衝突的發生。
git rebase
時,咱們還能對當前分支上的提交記錄作修改!採用 交互式變基(Interactive Rebase) 形式。 變基時提供了 6 種操做模式:
reword
:修改提交信息edit
:修改此提交squash
:將當前提交合併到以前的提交中fixup
:將當前提交合併到以前的提交中,不保留提交日誌消息exec
:在每個須要變基的提交上執行一條命令drop
:刪除提交以 drop
爲例:
squash
爲例:
e45cb
(+styles.css) 合併到
ec5be
(+index.js) 提交後,兩個提交從新 hash 出了
c4ec9
(+styles.css、+index.js)這個提交記錄。
git reset
)若是由於某些緣由(好比新提交致使了 BUG,或只是一個 WIP 提交),須要撤回提交,那麼可使用 git reset
指令。 git reset
能夠控制當前分支回撤到某次提交時的狀態。
執行軟重置時,撤回到特定提交以後,已有的修改會保留。
如下圖爲例:9e78i
提交添加了 style.css
文件,035cc
提交添加了 index.js
文件。使用軟重置,咱們能夠撤銷提交記錄,可是保留新建的 style.css
和 index.js
文件。
git status
指令查看,發現新建的
style.css
和
index.js
的兩個文件還在,不過對應的提交記錄已經移除。這很好,咱們能夠對這些文件內容從新編輯,稍後再作提交。
有時重置時,無需保留提交已有的修改,直接將當前分支的狀態恢復到某個特定提交下,這種重置稱爲硬重置,須要注意的是,硬重置還會將當前工做目錄(working directory)中的文件、已暫存文件(staged files)所有移除!💣
使用git status
查看,發現當前操做空間空空如也。Git 丟棄了
9e78i
和
035cc
兩次提交引入的修改,將倉庫重置到
ec5be
時的狀態。
git revert
)另外一種撤銷更改的方式,是使用 git revert
指令。用於還原某次提交的修改,會建立一個包含已還原更改的 新提交記錄! 舉個例子,咱們在 ec5be
上添加了 index.js
文件。以後發現並不須要這個文件。那麼就可使用 git revert ec5be
指令還原以前的更改。
新的提交記錄 9e78i
還原了 ec5be
引入的更改。git revert
能夠在不修改分支歷史的前提下,還原某次提交引入的更改。
git cherry-pick
)若是某個分支上的某次提交的修改正是當前分支須要的,那咱們可使用 cherry-pick
命令檢出某次的提交更改做爲新的提交添加到當前分支上面。
舉個例子(以下圖所示):dev
分支上的 76d12
提交添加了 index.js
文件,咱們須要將本次提交更改加入到 master
分支,那麼就可使用 git cherry-pick 76d12
單獨檢出這條記錄修改。
如今 master
分支包含了 76d12
中引入的修改,並添加了一條提交記錄 9e78i
。
git fetch
)假設,咱們在一個有關聯遠程分支(好比:在 Github 上)的分支上工做,那麼就要面臨一個問題——你和你的同事都這個分支上工做,你的同事將他作的更改(好比一個 quick fix)提交到了遠程分支上,而這些提交是你本地沒有的。
此時,就要使用 git fetch
指令將遠程分支上的最新的修改下載下來。
能夠看見,git fetch
指令並無影響本地分支。
git pull
)除了 git fetch
,咱們還能使用 git pull
獲取遠程分支數據。有什麼不一樣呢?git pull
指令實際作了兩件事:git fetch
和 git merge
。
以下圖所示:
譯註:這裏的圖畫的是有問題的——當前主分支並無新的提交,所以 git merge 的結果是直接將遠程分支上的提交添加到當前分支以後,而不是如圖所示的產生一個合併提交。
git reflog
)每一個人都會犯錯,舉一個例子:假設你不當心使用 git reset
命令硬重置倉庫到某個提交。後面忽然想到,重置致使了一些已有的正常代碼的誤刪! git reflog
是一個很是有用的命令,用於顯示全部已執行操做的日誌!包括合併、重置、還原:基本上記錄了對分支的任何更改。
git reflog
的信息經過重置
HEAD
輕鬆地重作此操做!
假設,咱們不想合併 origin/master
分支了。執行 git reflog
命令,咱們看到合併以前的倉庫狀態位於 HEAD@{1}
這個地方,咱們使用 git reset
指令將 HEAD
頭指向 HEAD@{1}
。
能夠看見,最新的操做信息也已經記錄到 reflog
中了!
(正文完)
廣告時間(長期有效)
我有一位好朋友開了一間貓舍,在此幫她宣傳一下。如今貓舍裏養的都是布偶貓。若是你也是個愛貓人士而且有須要的話,不妨掃一掃她的【閒魚】二維碼。不買也沒關係,看看也行。
(完)