Git Commit 和 commit-id


commit-id

姑且這么稱呼每一個 commit 所獨有的 id 為 commit-id 。所以 commit-id 都是用來唯一標識每一個 commit 的,使用 git log 命令可以看到一大堆 hash 化的 commit-id 。

現在我們定義每個 commit-id 所對應的文件區的代碼( 用代碼為了好理解 ) 改動為 δ( 建議讀成 delta )。后面所有操作都是基於 commit-id 操作的,所以大家要清楚 Git 的原子粒度最細就到 commit-id 了。

::: tip 補充
總有人糾結同一次 commit 里的兩個文件改動,由於后悔想分別進行 xxx 處理怎么辦?只能涼拌,沒有可能的!因為 Git 管理的粒度不到這里。
:::

Git 操作時要有 HEAD 概念。可以理解成 HEAD 就是一個指針,指向一個 commit-id 。就算你以為你的 HEAD 指向的是一個 branch ,其實底層也是指向的這個 branch 的最后、也就是的最新的那一個 commit-id 。

所以這里要清楚的一點是,HEAD 並非只能指向一個 branch(它的尾部 commit-id),它其實可以指向任何一個 commit-id 。

checkout 命令

git checkout 應該是 Git 里最復雜的命令,因為會根據后面加的參數的不同,它的底層行為會有很大的差異。這里只提下最簡單的。

檢出操作,或者理解成查看操作。

git checkout <branchName> 是檢出到某一個分支的意思,執行這個操作以后你的 HEAD 指針就會指向 <branchName> 分支下最后、也就是最新的那個 commit-id 上去,並且你的工作目錄( 代碼 )也會變成這個 commit-id 狀態下的模樣。

事實上 git checkout 后面可以加很多別的內容。比如,直接加某個 commit-id:git checkout <commit-id>

這樣的意思就是讓你的 HEAD 指向某一個 commit-id( 當然你的工作區也會相應刷新 ),這種情況下你不屬於任何分支,所以可以理解成 HEAD 處於一種游離態。假如這時你慌了,想回到一個常規狀態:

  • 可以選擇 git checkout <anyBranchName> 來切換回任何一個分支;

  • 也可以選擇 git branch <newBranchName> 來強勢地說:“我不后悔!就拿現在這個游離態作為基態建立一個新的偉大分支——newBranchName!”

從此不再游離。

希望你讀到這里能夠深有體會,因為很多復雜的事情都會建立在各種 checkout 之上。

reset 命令

假如你有連續 4 個 commit:commit-id1commit-id2commit-id3commit-id4 。當你后悔搞了 commit-id3commit-id4 ,你可以反悔並且悄悄: git reset commit-id2 。意思就是說:“我后悔了,悄悄把我后面的腳印擦掉吧,只留到 commit-id2”。

這樣操作以后執行 git log 就不會看到你后面 commit-id3commit-id4 的痕跡( 表面上看不到,Git 會給你留途徑讓你看到痕跡,這里不繼續延伸了 )。當然了建議 git reset 后面加一個 --hard 參數讓你改寫歷史的時候工作區也跟上一起刷新,最后推薦的命令是 git reset --hard commit-id2

revert 命令

假如你有連續 4 個 commit:commit-id1 、commit-id2 、commit-id3 、commit-id4 。當你后悔搞了 commit-id3 之后,你可以反悔並公開:git revert commit-id3

這樣操作以后你的 commit 樹就變成了 commit-id1,commit-id2,commit-id3,commit-id4,commit-id5 這個樣子,如果 commit-id3 體現在工作區的變動是 δ 的話,commit-id5 體現在工作區的變動就是 -δ ,是 commit-id3 的反向變動。也就是說 commit-id5 是對 commit-id3 的一種抵消。

reset 與 revert 對比

可見 revert 是有痕跡的反悔,相對於 reset 來說,revert 的后悔不僅沒有減少 commit 數量,反而會增加之。

::: tip 友情提示
在沒有把本地庫和遠程庫和多人協作搞透徹前,reset命令慎用哦,這里就不再深挖了,有興趣的老爺們可以另行提問。
:::

還有一個最重要的區別就是:reset 是 “ reset 到 xxx ”;revert 是 “ revert 掉 xxx ”。也就是說:

  • reset 處理的是一個區間,是從 HEAD 到你指定的 commit-id 之間的所有 commit-id 全部抹除,所以很省力;
  • revert 一次命令只能處理一個 commit-id ,所以對於大區間來說會比較費勁。

revert 最主要的一件事情要理解:假如你站在大樓的 10 層,想把第 8 層和第 9 層干掉的話,那么先 revert 第 9 層,再 revert 第 8 層,原因自己分析吧。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM