git stash與git commit的區別
問題的出現
寫這篇文章的緣由是在工作中初次使用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