[譯] 圖解經常使用的 Git 指令含義

原文連接:CS Visualized: Useful Git Commands,by Lydia Hallie(有刪改)。css

本文會介紹一些經常使用 Git 指令的圖解說明。包括:git

合併(git merge

當項目中多條功能分支時,有時就須要使用 git merge 命令,指定將某個分支的提交合併到當前分支。Git 中有兩個合併策略:fast-forwardno-fast-forwardfetch

fast-forward(--ff

若是當前分支,在合併分支前,沒有作過額外提交。那麼合併分支的過程不會產生的新的提交記錄,而是直接將分支上的提交添加進來。這稱爲 fast-forward 合併。 ui

如今 dev 分支上的修改已所有合併到主分支 master 上。那 no-fast-forward 又是什麼呢?

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

image.png

若是此時將 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.cssindex.js 文件。

使用 git status 指令查看,發現新建的 style.cssindex.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 fetchgit merge

以下圖所示:

譯註:這裏的圖畫的是有問題的——當前主分支並無新的提交,所以 git merge 的結果是直接將遠程分支上的提交添加到當前分支以後,而不是如圖所示的產生一個合併提交。

Reflog(git reflog

每一個人都會犯錯,舉一個例子:假設你不當心使用 git reset 命令硬重置倉庫到某個提交。後面忽然想到,重置致使了一些已有的正常代碼的誤刪! git reflog 是一個很是有用的命令,用於顯示全部已執行操做的日誌!包括合併、重置、還原:基本上記錄了對分支的任何更改。

若是你不幸犯錯了,你可使用 git reflog 的信息經過重置 HEAD 輕鬆地重作此操做!

假設,咱們不想合併 origin/master 分支了。執行 git reflog 命令,咱們看到合併以前的倉庫狀態位於 HEAD@{1} 這個地方,咱們使用 git reset 指令將 HEAD 頭指向 HEAD@{1}

能夠看見,最新的操做信息也已經記錄到 reflog 中了!

(正文完)


廣告時間(長期有效)

我有一位好朋友開了一間貓舍,在此幫她宣傳一下。如今貓舍裏養的都是布偶貓。若是你也是個愛貓人士而且有須要的話,不妨掃一掃她的【閒魚】二維碼。不買也沒關係,看看也行。

(完)

相關文章
相關標籤/搜索