問題的出現
寫這篇文章的緣由是在工作中初次使用Git的時候遇到了一個奇怪的現象,即每次提交代碼的時候,如果沒有及時拉取代碼就會導致本地庫的代碼不是最新的,這樣自己修改代碼之后想要push到遠程倉庫的時候就會遭到拒絕,每次被拒絕以后我會先拉取代碼,然后再繼續push,這樣可以成功提交代碼,可是會產生兩個提交對象,一個是我改動產生的提交對象(這個是應該有的),可是還會產生另外一個Merge branch…的提交對象,這個對象里面是我未拉取的別人的提交,最后作為了我的提交push到了遠程倉庫,這樣的現象會使得提交歷史記錄比較混亂,容易讓人迷惑,稍有不慎,就會把別人的提交誤認為其他人或自己的。
由於對Git的了解有限,所以這個現象產生的原因自己一直百思不得其解,直到有一天通過看書與討論總算弄清楚了現象產生的原因。
隱藏的區別
在項目開發的過程中,我使用的開發工具是STS,而另一位同事使用的開發工具是IntelliJ IDEA,里面分別集成了Git的插件,使用STS的時候會出現前述的現象,可是使用IDEA在上述情況下並不會產生兩個提交對象,也就是不會把他人的提交變成自己的提交再重新提交一遍,我們推測一定是兩個工具默認使用的Git命令不同,所以導致產生的現象不一樣。
最后,我們使用命令行重現了兩種現象,終於弄懂了不同的Git命令的區別,本質上就是git stash
命令和git commit
命令的區別。如果我們知道Git的基本原理,那就一定知道Git中存儲的是文件的快照而非每個文件與初始版本的差異,那么在每次提交的時候,Git都會對當時的全部文件制作一個快照並保存這個快照的索引(存儲在提交對象中)。假設我們在master
分支進行開發工作:
A local
/
D---E---A' master
在拉取了E
(字母代表一個提交對象)提交之后,我們忘記拉取最新的代碼就進行了修改,這時候master
分支上的提交已經變成了A'
。
(1) 如果我們使用git commit
命令,那么我們本地就會產生一個A
的提交對象,那么git pull
的時候便需要把master
分支合並到本地(可能需要解決沖突),然后再提交:
A local
/ \
D---E---A' master
合並后產生了一個M
提交對象:
A---M local
/
D---E---A' master
最后git push
提交到master
分支上,則會產生兩個提交:
D---E---A'---A---M master
(2) 如果我們使用git stash
命令,那么我們本地就不會產生新的提交對象,而是把本地的更改先行緩存,那么git pull
的時候便可以直接把本地的HEAD
更新為A'
:
A' local
/
D---E---A' master
然后再使用git stash pop
命令將本地的修改恢復(可能需要解決沖突),這就相當於我們在A'
的基礎上進行了修改,然后進行git commit
產生了新的提交對象B
:
A'---B local
/
D---E---A' master
最后git push
提交到master
分支上,則只會產生一個提交:
D---E---A'---B master
總結
奇怪現象出現的原因並不是Git的bug,而是我們操作方式的不對。通過這個實驗,我們也了解了在兩個不同的IDE中對於Git操作的默認指令也是不一樣的,STS中的EGit插件對於本地的修改會默認git add
,而IDEA中集成的Git對本地的修改會默認git stash
。
版權聲明:本文為CSDN博主「cloud_yf」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u010629610/article/details/87335894