本地修改
由於以下修改本身是對版本歷史的修改,在需要push到遠程倉庫時,往往是不成功的,只能強行push,這樣會出現的一個問題就是,如果你是push到多人協作的遠程倉庫中,會對其他人的遠程操作構成影響。通常情況下,建議與項目遠程倉庫的管理員進行溝通,在完成你強制push操作后,通知其他人同步。
-
修改最近一次的commit
修改提交的描述
git commit --amend
然后會進入一個文本編輯器界面,修改commit的描述內容,即可完成操作。
修改提交的文件
git add <filename> # 或者 git rm git commit --amend # 將緩存區的內容做為最近一次提交
-
修改任意提交歷史位置的commit
可以通過變基命令,修改最近一次提交以前的某次提交。不過修改的提交到當前提交之間的所有提交的hash值都會改變。
變基操作需要非常小心,一定要多用git status
命令來查看你是否還處於變基操作,可能某次誤操作的會對后面的提交歷史造成很大影響。首先查看提交日志,以便變基后,確認提交歷史的修改
git log
變基操作。 可以用
commit~n
或commit^^
這種形式替代:前者表示當前提交到n次以前的提交,后者^
符號越多表示的范圍越大,commit可以是HEAD或者某次提交的hash值;-i
參數表示進入交互模式。git rebase -i <commit range>
以上變基命令會進入文本編輯器,其中每一行就是某次提交,把
pick
修改為edit
,保存退出該文本編輯器。**注意:**變基命令打開的文本編輯器中的commit順序跟
git log
查看的順序是相反的,也就是最近的提交在下面,老舊的提交在上面**注意:**變基命令其實可以同時對多個提交進行修改,只需要修改將對應行前的
pick
都修改為edit
,保存退出后會根據你修改的數目多次打開修改某次commit的文本編輯器界面。但是這個范圍內的最終祖先commit不能修改,也就是如果有5行commit信息,你只能修改下面4行的,這不僅限於commit修改,重排、刪除以及合並都如此。git commit --amend
接下來修改提交描述內容或者文件內容,跟最近一次的commit的操作相同,不贅述。
然后完成變基操作
git rebase --continue
有時候會完成變基失敗,需要
git add --all
才能解決,一般git會給出提示。再次查看提交日志,對比變基前后的修改,可以看到的內的所有提交的hash值都被修改了
git log
如果過了一段時間后,你發現這次歷史修改有誤,想退回去怎么辦?請往下繼續閱讀
-
重排或刪除某些提交
變基命令非常強大,還可以將提交歷史重新手動排序或者刪除某次提交。這為某些誤操作,導致不希望公開信息的提交,提供了補救措施
git rebase -i <commit range>
如前面描述,這會進入文本編輯器,對某行提交進行排序或者刪除,保存退出。可以是多行修改。
后續操作同上。
-
合並多次提交
非關鍵性的提交太多會讓版本歷史很難看、冗余,所以合並多次提交也是挺有必要的。同樣是使用以上的變基命令,不同的是變基命令打開的文本編輯器里的內容的修改。
將
pick
修改為squash
,可以是多行修改,然后保存退出。這個操作會將標記為squash
的所有提交,都合並到最近的一個祖先提交上。**注意:**不能對的第一行commit進行修改,至少保證第一行是接受合並的祖先提交。
后續操作同上。
-
分離某次提交
變基命令還能分離提交,這里不描述,詳情查看后面的參考鏈接
-
終極手段
git還提供了修改版本歷史的“大殺器”——
filter-branch
,可以對整個版本歷史中的每次提交進行修改,可用於刪除誤操作提交的密碼等敏感信息。刪除所有提交中的某個文件
git filter-branch --treefilter 'rm -f password.txt' HEAD
將新建的主目錄作為所有提交的根目錄
git filter-branch --subdirectory-filter trunk HEAD
本地回退
回退操作也是對過往提交的一劑“后悔葯”,常用的回退方式有三種:checkout
、reset
和revert
-
checkout
對單個文件進行回退。不會修改當前的HEAD指針的位置,也就是提交並未回退
可以是某次提交的hash值,或者HEAD(缺省即默認)
git checkout <commit> -- <filename>
-
reset
回退到某次提交。回退到的指定提交以后的提交都會從提交日志上消失
**注意:**工作區和暫存區的內容都會被重置到指定提交的時候,如果不加--hard
則只移動HEAD的指針,不影響工作區和暫存區的內容。git reset --hard <commit>
結合
git reflog
找回提交日志上看不到的版本歷史,撤回某次操作前的狀態git reflog # 找到某次操作前的提交hash值 git reset <commit>
這個方法可以對你的回退操作進行回退,因為這時候
git log
命令已經找不到歷史提交的hash值了。 -
revert
這個方法是最溫和,最受推薦的,因為本質上不是修改過去的版本歷史,而是將回退版本歷史作為一次新的提交,所以不會改變版本歷史,在push到遠程倉庫的時候也不會影響到團隊其他人。
git revert <commit>
遠程修改
對遠程倉庫的版本歷史修改,都是在本地修改的基礎上進行的:本地修改完成后,再push到遠程倉庫。
但是除了git revert
可以直接push,其他都會對原有的版本歷史修改,只能使用強制push
git push -f <remote> <branch>
總結
git commit --amend
改寫單次commitgit rebase -i <commit range>
刪改排以及合並多個commitgit checkout <commit> -- <filename>
獲取歷史版本的某個文件git reset [--hard] <commit>
移動HEAD指針git revert <commit>
創建一個回退提交git push -f <remote> <branch>
強制push,覆蓋原有遠程倉庫