一看就懂:十幾張動圖教你快速學會Git命令!


一看就懂:十幾張動圖教你快速學會Git命令!


雖然 Git 是一個強大的工具,但是我覺得大部分人都會同意我說的:它也可以是一個……噩夢!我一直覺得,使用 Git 的時候把操作過程在腦海裡視覺化會非常有用:當我執行某個命令的時候,分支之間是如何交互的?又是如何影響提交歷史的?當我在​master​分支執行​hard reset​、​force push​到 ​origin​、在​.git​文件夾執行​rimraf​的時候,為什麼我的同事都哭了?

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

merge

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

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

no-fast-forward​。

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

fast-forward (​--ff​)

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

一看就懂:十幾張動圖教你快速學會Git命令!


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

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

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

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

一看就懂:十幾張動圖教你快速學會Git命令!


也沒毛病!現在​master​分支上有了我們在​dev​分支上做的所有變更。

合併衝突

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

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

一看就懂:十幾張動圖教你快速學會Git命令!


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

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

一看就懂:十幾張動圖教你快速學會Git命令!


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

rebase

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

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

一看就懂:十幾張動圖教你快速學會Git命令!


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

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

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

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

交互式 rebase

在 ​rebase​ 之前,我們還可以修改!這是通過交互式 rebase 實現的。交互式 rebase 也可以用於當前正在處理的分支,在希望修改某些提交的時候。

對於即將 rebase 的提交,可以執行 6 種操作:

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

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


一看就懂:十幾張動圖教你快速學會Git命令!

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

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

reset

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

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

soft reset

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

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

一看就懂:十幾張動圖教你快速學會Git命令!

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

hard reset

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

一看就懂:十幾張動圖教你快速學會Git命令!


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

revert

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

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

一看就懂:十幾張動圖教你快速學會Git命令!


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

cherry-pick

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

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

一看就懂:十幾張動圖教你快速學會Git命令!

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

fetch

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

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

一看就懂:十幾張動圖教你快速學會Git命令!


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

pull

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

一看就懂:十幾張動圖教你快速學會Git命令!


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

reflog

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

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

一看就懂:十幾張動圖教你快速學會Git命令!


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

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

一看就懂:十幾張動圖教你快速學會Git命令!


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

總結

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


原文:
https://dev.to/lydiahallie/cs-visualized-useful-git-commands-37p1

我是零度橙子,科技達人,谷歌認證雲計算架構師,AWS認證devops專家,歡迎大家關注我,瞭解有用有趣的科技知識~


分享到:


相關文章: