1. 程式人生 > >Git使用(4)修改提交結果、版本回退與衝突解決

Git使用(4)修改提交結果、版本回退與衝突解決

1.檢視版本之間差異

1.1檢視有哪些資料夾/檔案有差異

git diff
顯示工作目錄與暫存區檔案之間的差異
git diff --cached
顯示暫存區與git倉庫之間的差異
git diff HEAD
顯示工作目錄與git倉庫之間的差異
(以上三種都是現在跟前面相比較)

git diff HEAD – ./test
比較當前分支上,工作區與HEAD 在test檔案的變化(常用,注意中間是兩橫)
git diff – HEAD ./dir
比較當前分支上,工作區與HEAD 在dir資料夾下變化(常用)
git diff – ./test比較工作區和暫存區之間的變化
git diff test_branch
比較test_branch 分支而非當前分支,比較內容同上
git diff commit1 commit2

:如
git diff HEAD^ HEAD
比較HEAD的前一個版本和HEAD
1.2 檢視某檔案的修改記錄:
git log -p ./dir/file1.txt
會打印出所有修改記錄及其版本HASH值。接下來可以通過版本回退找到該檔案中那個版本的內容(參見2.2)

2.修改commit資訊

2.1 修改本地 commit資訊

加入commit 提交了,但又發現註釋寫得不夠完善,想再次修改,怎麼辦?
可以使用:

git commit -- amend

隨後就像操作vim一樣進行操作,修改完畢,:q,儲存即可。
還有一種方法,是下邊介紹的:

git reset
--soft HEAD^

修改後再重新提交即可。

2.2修改遠端commit資訊

加入不小心提交到遠端倉庫,但發現commit寫得有問題,怎麼辦?
方法1:
回退本地版本,再強制同步遠端版本,使之與本地同步:

git reset --hard HEAD^
git push -f origin localRepo:remoteRepo

3.版本回退與歷史修改

3.1本地整個版本回退

方法1:git reset
知道版本號(就是那個hash值)後,就可以
git reset了,它有三個引數:
git reset –mixed //預設,回退版本庫歷史(即移動HEAD指標),工作區不變,暫存區(index)清空(有的地方說快取區reset,有的地方使快取區和當前HEAD內容一樣,但兩種說法實質是一樣的,因為快取區是用來記錄與當前working directory相比變化的內容(./git/index是一個二進位制檔案,包含已排好序的檔名、檔案索引、檔案元資料等,這些資料一起構成當前的快取),所謂當前index與working directory一致,就相當於index清零)
git reset –soft //回退版本庫歷史到某一版本,工作區不變,暫存區(index)不變。
git reset –hard//回退版本庫、工作區到某一版本,清空暫存區(危險,一般應在此操作前git status 確認無重要更改)
其差別可用此圖解釋:
這裡寫圖片描述


git reset –hard d25062cd5

不論是hard還是soft,現在比d25062cd5更新的幾個提交都變成了懸掛提交。下次Git執行垃圾回收的時候,這幾個提交會被刪除。

常用的還有:git reset HEAD //清空快取區,回退到最近一次提交的版本。

如果後悔了想回退到之前的版本,但此處找不到最新那個版本的id了,怎麼辦?可以通過:
git reflog
git reflog可以記錄自己的所有操作,包括所有HAED的變動情況,以及對應的HEAD的hash值。

ea34578 [email protected]{0}: reset: moving to HEAD^
3628164 [email protected]{1}: commit: append
ea34578 [email protected]{2}: commit: add distributed
cb926e7 [email protected]{3}: commit (initial): wrote a readme file

發現最後一次提交,即最新版本是3628164。隨後可以git reset –HARD 到之前那個HEAD雜湊值所在版本。
除此之外
如果原來版本中有檔案沒有被提交到版本庫裡,這樣版本之間切換後找不到原來的了。只要之前將該檔案git add到快取區了,也可通

git fsck --lost-found

然後就能在.git/lost-found下找到找到快取檔案
方法2: git revert撤銷上一次提交
git revert 和git reset的差別是,git revert是程式碼回退到原來版本,但不會刪除提交歷史,同時會產生新的提交id,而git reset是回退程式碼,同時刪除了提交歷史。
git revert 語法與git reset差不多

git revert HEAD
git revert commit_id

隨後會出現編輯框,可以編輯自己的一些commit資訊。
revert 是撤銷一次提交,commit_id代表的版本被撤銷,所以最終是回滾到commit id的前一次提交。

如果使用 revert 撤銷的不是最近一次提交,那麼一定會有程式碼衝突,需要你合併程式碼,合併程式碼只需要把當前的程式碼全部去掉,保留之前版本的程式碼就可以。所以一般使用git reset來回滾到比較遠的版本,以免大量的程式碼衝突。
方法3:

3.2本地部分檔案回退

接1.2:恢復某檔案/資料夾的內容到某版本
git checkout – ./dir 恢復到上一個版本

一種是該目錄下自修改後還沒有被放到暫存區(即沒執行過git add),現在,撤銷修改就回到和版本庫一模一樣的狀態;
一種是該目錄已經新增到暫存區後,又作了修改,現在,撤銷修改就回到新增到暫存區後的狀態。
所以如果強制要會退到版本庫歷史中儲存的最新版本,建議:git checkout HEAD –./dir

git checkout d25062cd5 – ./file.txt //恢復到某一指定版本

git checkout //恢復版本到上一版本
git checkout d25062cd5 //恢復版本到某歷史版本

3.3遠端倉庫版本回退

假如不小心有錯誤的提交,則可以使用以下方式:
如果是私有開發分支,或者不想留下撤銷的記錄,則可以:
git push -f
直接將本地版本回退,然後git push -f,覆蓋遠端分支。好用無風險。
更暴力方法
或者:直接從那個錯誤的提交的前一次拉取一份程式碼放到其他目錄,然後將master程式碼全部刪除,把那份新程式碼方進去,然後提交。
對於公共開發分支,考慮到可能在我提交後有人已經pull,所以需要保留所有版本記錄:則只能藉助於:
1) git revert HEAD

3.4刪除某次較遠的提交記錄

git log//查詢對應的記錄id
git rebase -i commit_id//會跳出一個編輯框,需要在編輯框中將版本號對應的一行刪除。
git push -f

附錄:

HEAD, HEAD^, HEAD^^, HEAD~3,HEAD~100:當前版本庫最新歷史版本,上一個版本,上上個,上上上(第3)個,倒數第100個

參考: