常用Git命令動畫演示

轉載自:https://blog.zzonn.com/2020/05/08/%E5%B8%B8%E7%94%A8Git%E5%91%BD%E4%BB%A4%E5%8A%A8%E7%94%BB%E6%BC%94%E7%A4%BA/

 

雖然 Git 是一個強大的工具,但是我覺得大部分人用起來都會認爲很複雜,還容易犯錯!
當我執行某個命令的時候,分支之間是如何交互的?又是如何影響提交歷史的?
當我在master分支執行hard resetforce push到 origin、在.git文件夾執行rimraf的時候,爲什麼我的同事都哭了?

我認爲創建一些最常見、最實用的命令的可視化示例是最佳使用指南!接下來介紹的這些命令,很多都有可選參數,用於改變命令的行爲。文中的示例只討論命令的默認行爲,不會涉及太多的配置選項。這些命令包括 mergerebasereset, revertcherry-pickfetchpullreflog 等。

merge(合併)

多分支可以非常方便地將新的改動互相隔離,並確保你不會意外地將未經批准或破壞性的變更推到生產環境。一旦變更被批准,我們就能在生產分支中得到這些變更。

從一個分支獲取變更到另一個分支的方式之一是執行git merge命令。Git 有兩類合併操作:fast-forward 和no-fast-forward

這麼說你可能沒什麼概念,我們來看看區別吧。

fast-forward (--ff)

如果當前分支與即將合並過來的分支相比,沒有額外的提交,這種就是fast-forward合併。Git 很會偷懶,它會首先嚐試最簡單的方案,即fast-forward。這種合併方式不會創建新的提交,只是把另一個分支的提交記錄直接合併到當前分支。

fast-forward merge

現在我們在master分支上有了dev分支上的所有變更。那麼,no-fast-forward 又是什麼呢?

no-fast-foward (--no-ff)

跟即將合並過來的分支比較,當前分支如果沒有額外的提交,這固然很好,但實際情況往往不是這樣!如果我們在當前分支上也提交了一些改動,那麼 Git 就會執行no-fast-forward合併。

對於 no-fast-forward 合併,Git 會在當前分支上創建一個新的合併提交。該提交的父提交同時指向當前分支和合並過來的分支。

no-fast-forward

現在master分支上有了我們在dev分支上做的所有變更。

Merge Conflicts(合併衝突)

雖然 Git 擅長決定如何合併分支和更改文件,但它也不是總能自己做出決定。當我們試圖合併的兩個分支在同一文件的同一行上都有改動時,或者一個分支刪除了文件,另一個分支又修改了它,都可能發生這種情況。

這種情況下,Git 會要求你幫助決定要保留哪邊的改動。假設在兩個分支上,我們都編輯了README.md文件的第一行:

README.md

如果把dev合併到 master,會導致合併衝突:你是要 Hello! 呢,還是要 Hey! ?

合併分支時,Git 會顯示衝突的位置。我們可以手動刪除不想保留的改動,然後保存,再添加改動後的文件(git add)並提交。

合併衝突

合併衝突雖然很煩人,但也是合理的:Git 不應該自作主張保留哪邊的改動。

rebase(變基)

剛剛我們看到了如何通過執行git merge將一個分支的改動應用到另一個分支。另一種方式是使用git rebase

git rebase命令複製當前分支的提交,然後把這些提交放到指定分支之上。

git rebase

現在 master 分支上的所有改動都跑到dev分支上了!

merge相比,最大的區別是 Git 不會去找出哪些文件需要保留,哪些文件不需要保留。我們要rebase的分支總是包含了我們想要保留的最新改動。這種方式不會有合併衝突,並且保持了良好的線性 Git 歷史記錄。

這個例子演示了在 master分支上執行rebase。不過,在大項目裏你可能不會這麼做。git rebase命令會修改項目歷史記錄,因爲複製的提交會產生新的 hash

當你在特性分支上開發時,master分支有更新的時候,rebase很有用。這樣你在當前分支就能拿到所有更新,避免了將來可能的合併衝突。

Interactive Rebase(交互式變基)

在 rebase 之前,我們還可以修改!這是通過交互式 rebase 實現的。交互式 rebase 也可以用於當前正在處理的分支,在希望修改某些提交的時候。
對於即將 rebase 的提交,可以執行 6 種操作:

reword:修改提交說明
edit:修改提交內容(amend)
squash:將該提交合併到前一個提交
fixup: 將該提交合併到前一個提交,不保留提交的日誌消息
exec: 在想要 rebase 的每一個提交上執行命令
drop: 刪除提交

這樣,我們就能完全控制提交記錄了。如果想刪除某個提交,只要 drop 它就行了。

Interactive Rebase

或者,如果我們想要把多個提交合併到一起,這樣歷史記錄會更清晰,也沒問題!

交互式 rebase 給了你對想要 rebase 的提交很多控制權,哪怕是當前的活動分支。

reset(重置)

有時候我們提交了一些改動,後來又不想要了。有可能是 WIP 提交,也可能是某個引入了 bug 的提交。這種情況,我們可以執行git reset

git reset會丟棄當前所有暫存的文件,並讓我們決定 HEAD 應該指向哪裏。

soft reset

soft reset 將HEAD 移動到指定的提交(或者相對於 HEAD 的位置索引),同時不會丟棄這些提交帶來的改動。

假設我們不想保留添加了style.css文件的提交 9e78i,也不想保留添加了index.js文件的提交 035cc 。但是,我們卻想要保留新增的style.cssindex.js文件。這裏用 soft reset 就非常合適。

soft reset

執行git status,你會看到我們依然能夠查看之前提交所做的改動。這很有用,因爲這樣我們就能繼續修改文件內容,後續再次提交了。

hard reset

有時候,我們不想保留某些提交帶來的改動。跟 soft reset 不一樣,我們不再需要訪問這些變動了。Git 應該簡單地重置到指定的提交,並且會重置工作區和暫存區的文件。

hard reset

Git 已經丟棄了9e78i 和 035cc 兩個提交引起的改動,並把狀態重置到了提交ec5be的位置。

revert(回滾)

撤銷改動的另一種方式是執行git revert。復原某個提交後,會創建一個新的提交,包含了恢復後的改動。

假設提交 ec5be 添加了一個index.js文件。隨後,我們發現實際上不再需要這個改動了,就可以恢復ec5be這個提交。

revert

提交9e78i恢復了 ec5be 這個提交帶來的改動。執行 git revert對於撤銷某個提交非常有用,同時又不會修改分支的歷史。

cherry-pick(提交揀選)

當活動分支需要某個分支的某個提交包含的改動時,我們可以用cherry-pick命令。通過cherry-pick某個提交,在當前活動分支上會創建一個新提交,包含了前者帶來的改動。

假設 dev 分支上的提交76d12改動了index.js文件,我們在master分支上也需要。我們不需要整個分支上的改動,只要這個提交。

cherry-pick

master分支現在也包含了76d12提交的改動了。

fetch(提取/獲取)

如果存在遠程分支,遠程分支可能有些提交是當前的本地分支沒有的。有可能是其他分支合並過去了,或者你的同事推送了某些改動,等等。

我們可以用git fetch 把這些改動獲取到本地。這不會影響本地分支,fetch 只是下載數據。

fetch

現在就可以看到從最近一次推送以來的所有變動。本地有了這些新數據,我們就可以決定如何使用了。

pull (拉取)

除了用git fetch 獲取遠程分支信息外,還可以用git pullgit pull實際上是兩個命令合而爲一:git fetchgit merge。當我們從 origin 拉取改動時,先是像git fetch一樣獲取所有數據,然後最新改動會自動合併到本地分支。

pull

這樣就跟遠程分支保持同步了,包含了所有的最新改動。

reflog (操作日誌)

每個人都會犯錯誤,這完全沒有關係!有時候你可能覺得自己把倉庫搞得一團糟,只想把它刪了完事。

git reflog是個非常有用的命令,可以顯示所有操作的日誌。包括 mergeresetrevert 等,基本上包括了對分支的任何更改。

reflog

如果出錯了,你可以根據reflog提供的信息通過重置 HEAD 來撤銷改動。

比如,我們實際上並不想合併分支。當我們執行 git reflog 命令時,我們看到在合併前倉庫位於HEAD@{1}。我們執行下git reset命令,讓 HEAD 重新指回原來的HEAD@{1} 位置。

reflog

我們可以看到,最新的操作也記錄到 reflog 裏了。

Git 還有很多有用的命令,篇幅所限不能一一列舉。希望通過上面這些形象的動畫演示,能夠更好地理解這些分支操作。

參考

https://dev.to/lydiahallie/cs-visualized-useful-git-commands-37p1https://hexo.io/docs/one-command-deployment.html)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章