雲栖号資訊:【 點選檢視更多行業資訊】
在這裡您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!
本文會介紹一些常用 Git 指令的圖解說明。
合并(git merge)
當項目中多條功能分支是,有時就需要使用 git merge 指令,指定将某個分支的送出合并到目前分支。Git 中有兩個合并政策:fast-forward 和 no-fast-forward。
fast-forward(--ff)
如果目前分支,在合并分支前,沒有做過額外送出。那麼合并分支的過程不會産生的新的送出記錄,而是直接将分支上的送出添加進來。這稱為 fast-forward 合并。

現在 dev 分支上的修改已全部合并到主分支 master 上。那 no-fast-forward 又是什麼呢?
no-fast-forward(--no-ff)
上面的場景很少遇到,基本是:在目前分支分離出子分支後,做了一些修改;而分離出的子分支也做了修改。這個時候再使用 git merge,就會觸發 no-fast-forward 政策了。
在 no-fast-forward 政策下,Git 會在目前分支(active branch)額外建立一個新的 合并送出(merging commit)。這條送出記錄既指向目前分支,又指向合并分支。
合并後,在目前主分支 master 上包含 dev 分支上的所有修改。
合并沖突
如果兩個分支的修改存在沖突:比如說同時修改了某個檔案的同一行;或者一個分支删除了檔案,另一個分支則修改了檔案——對于這種情況,Git 是無法自行決定合并政策的。這個時候,Git 就會把合并操作交給我們。
舉個例子,兩個分支對同一個 README.md 檔案做了修改。
如果此時将 dev 合并到 master,那麼就存在合并沖突了:标題是使用 Hello! 還是 Hey! 呢?
當在主分支上執行 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 的結果是直接将遠端分支上的送出添加到目前分支之後,而不是如圖所示的産生一個合并送出。
Reflog(git reflog)
每個人都會犯錯,舉一個例子:假設你不小心使用 git reset 指令硬重置倉庫到某個送出。後面突然想到,重置導緻了一些已有的正常代碼的誤删!
git reflog 是一個非常有用的指令,用于顯示所有已執行操作的日志!包括合并、重置、還原:基本上記錄了對分支的任何更改。
如果你不幸犯錯了,你可以使用 git reflog 的資訊通過重置 HEAD 輕松地重做此操作!
假設,我們不想合并 origin/master 分支了。執行 git reflog 指令,我們看到合并之前的倉庫狀态位于 HEAD@{1} 這個地方,我們使用 git reset 指令将 HEAD 頭指向 HEAD@{1}。
可以看見,最新的操作資訊也已經記錄到 reflog 中了!
【雲栖号線上課堂】每天都有産品技術專家分享!
課程位址:
https://yqh.aliyun.com/zhibo立即加入社群,與專家面對面,及時了解課程最新動态!
【雲栖号線上課堂 社群】
https://c.tb.cn/F3.Z8gvnK
原文釋出時間:2020-04-07
本文作者:zhangbao90s
本文來自:“
掘金”,了解相關資訊可以關注“掘金”