git reset(回退add操作)


Git的一般使用中,如果發現錯誤的將不想提交的文件add進入index之后,想回退取消,則可以使用命令:git reset HEAD <file>...,同時git add完畢之后,git也會做相應的提示,比如:

引用

 

# Changes to be committed: 

#   (use "git reset HEAD<file>..." to unstage) 

# new file:   Test.Scala 

 

git reset [--hard|soft|mixed|merge|keep] [<commit>HEAD]:將當前的分支重設(reset)到指定的<commit>或者HEAD(默認,如果不顯示指定commit,默認是HEAD,即最新的一次提交),並且根據[mode]有可能更新indexworking directory

下面列出一些git reset的典型的應用場景: 

A) 回滾add操縱 

引用

$ edit                                   (1) 

$ git add frotz.c filfre.c 

$ mailx                                  (2) 

$ git reset                              (3) 

$ git pull git://info.example.com/ nitfol (4) 

 

(1) 編輯文件frotz.c, filfre.c,做了些更改,並把更改添加到了index 

(2) 查看郵件,發現某人要你pull,有一些改變需要你merge下來 

(3) 然而,你已經把index搞亂了,因為indexHEAD commit不匹配了,但是你知道,即將pull的東西不會影響已經修改的frotz.cfilfre.c,因此你可以revert這兩個文件的改變。revert后,那些改變應該依舊在working directory中,因此執行git reset 

(4) 然后,執行了pull之后,自動mergefrotz.cfilfre.c這些改變依然在working directory中。 

 

B) 回滾最近一次commit 

引用

$ git commit ... 

$ git reset --soft HEAD^     (1) 

$ edit                       (2) 

$ git commit -a -c ORIG_HEAD (3) 

 

(1) 當提交了之后,你又發現代碼沒有提交完整,或者你想重新編輯一下提交的comment,執行git reset --soft HEAD^,讓working tree還跟reset之前一樣,不作任何改變。 

HEAD^指向HEAD之前最近的一次commit 

(2) working tree下的文件做修改 

(3) 然后使用reset之前那次commit的注釋、作者、日期等信息重新提交。注意,當執行git reset命令時,git會把老的HEAD拷貝到文件.git/ORIG_HEAD中,在命令中可以使用ORIG_HEAD引用這個commitcommit命令中 -a 參數的意思是告訴git,自動把所有修改的和刪除的文件都放進stage area,未被git跟蹤的新建的文件不受影響。commit命令中-c <commit> 或者 -C <commit>意思是拿已經提交的commit對象中的信息(作者,提交者,注釋,時間戳等)提交,那么這條commit命令的意思就非常清晰了,把所有更改的文件加入stage area,並使用上次的提交信息重新提交。 

 

C) 回滾最近幾次commit,並把這幾次commit放到叫做topicbranch上去。 

引用

$ git branch topic/wip    (1) 

$ git reset --hard HEAD~3  (2) 

$ git checkout topic/wip   (3)

 

(1) 你已經提交了一些commit,但是此時發現這些commit還不夠成熟,不能進入master分支,但你希望在新的branch上潤色這些commit改動。因此執行了git branch命令在當前的HEAD上建立了新的叫做 topic/wip的分支。 

(2) 然后回滾master branch上的最近三次提交。HEAD~3指向當前HEAD-3commitcommitgit reset --hard HEAD~3即刪除最近的三個commit(刪除HEAD, HEAD^, HEAD~2),將HEAD指向HEAD~3 

 

D) 永久刪除最后幾個commit 

引用

$ git commit ... 

$ git reset --hard HEAD~3   (1)

 

(1) 最后三個commit(即HEAD, HEAD^HEAD~2)提交有問題,你想永久刪除這三個commit 

 

E) 回滾mergepull操作 

引用

$ git pull                        (1) 

Auto-merging nitfol 

CONFLICT (content): Merge conflict innitfol 

Automatic merge failed; fix conflicts andthen commit the result. 

$ git reset --hard                (2) 

$ git pull . topic/branch         (3) 

Updating from 41223... to 13134... 

Fast-forward 

$ git reset --hard ORIG_HEAD      (4)

 

(1) origin拉下來一些更新,但是產生了很多沖突,你暫時沒有這么多時間去解決這些沖突,因此你決定稍候有空的時候再重新pull 

(2) 由於pull操作產生了沖突,因此所有pull下來的改變尚未提交,仍然再stage area中,這種情況下git reset --hard git reset --hard HEAD意思相同,即都是清除indexworking tree中被搞亂的東西。 

(3) topic/branch合並到當前的branch,這次沒有產生沖突,並且合並后的更改自動提交。 

(4) 但是此時你又發現將topic/branch合並過來為時尚早,因此決定退滾merge,執行git reset --hard ORIG_HEAD回滾剛才的pull/merge操作。說明:前面講過,執行git reset時,git會把reset之前的HEAD放入.git/ORIG_HEAD文件中,命令行中使用ORIG_HEAD引用這個commit。同樣的,執行pullmerge操作時,git都會把執行操作前的HEAD放入ORIG_HEAD中,以防回滾操作。 

 

F) 在被污染的working tree中回滾merge或者pull 

引用

$ git pull                        (1) 

Auto-merging nitfol 

Merge made by recursive. 

nitfol               |   20 +++++---- 

... 

$ git reset --merge ORIG_HEAD     (2)

 

(1) 即便你已經在本地更改了一些你的working tree,你也可安全的git pull,前提是你知道將要pull的內容不會覆蓋你的working tree中的內容。 

(2) git pull完后,你發現這次pull下來的修改不滿意,想要回滾到pull之前的狀態,從前面的介紹知道,我們可以執行git reset --hard ORIG_HEAD,但是這個命令有個副作用就是清空你的working tree,即丟棄你的本地未add的那些改變。為了避免丟棄working tree中的內容,可以使用git reset --merge ORIG_HEAD,注意其中的--hard換成了 --merge,這樣就可以避免在回滾時清除working tree 

 

G) 被中斷的工作流程 

在實際開發中經常出現這樣的情形:你正在開發一個大的feature,此時來了一個緊急的bug需要修復,但是目前在working tree中的內容還沒有成型,還不足以commit,但是你又必須切換的另外的branchfix bug。請看下面的例子 

引用

$ git checkout feature ;# you were workingin "feature" branch and 

$ work work work       ;#got interrupted 

$ git commit -a -m "snapshot WIP"                (1) 

$ git checkout master 

$ fix fix fix 

$ git commit ;# commit with real log 

$ git checkout feature 

$ git reset --soft HEAD^ ;# Go back to WIPstate  (2) 

$ git reset                                     (3)

 

(1) 這次屬於臨時提交,因此隨便添加一個臨時注釋即可。 

(2) 這次reset刪除了WIP commit,並且把working tree設置成提交WIP快照之前的狀態。 

(3) 此時,在index中依然遺留着“snapshot WIP”提交時所做的uncommit changesgit reset將會清理index成為尚未提交"snapshot WIP"時的狀態便於接下來繼續工作。 

 

(H) Reset單獨的一個文件 

假設你已經添加了一個文件進入index,但是而后又不打算把這個文件提交,此時可以使用git reset把這個文件從index中去除。 

引用

$ git reset -- frotz.c                     (1) 

$ git commit -m "Commit files inindex"     (2) 

$ git add frotz.c                          (3)

 

(1) 把文件frotz.cindex中去除, 

(2) index中的文件提交 

(3) 再次把frotz.c加入index 

 

(I) 保留working tree並丟棄一些之前的commit 

假設你正在編輯一些文件,並且已經提交,接着繼續工作,但是現在你發現當前在working tree中的內容應該屬於另一個branch,與這之前的commit沒有什么關系。此時,你可以開啟一個新的branch,並且保留着working tree中的內容。 

引用

$ git tag start 

$ git checkout -b branch1 

$ edit 

$ git commit ...                          (1) 

$ edit 

$ git checkout -b branch2                  (2) 

$ git reset --keep start                   (3)

 

(1) 這次是把在branch1中的改變提交了。 

(2) 此時發現,之前的提交不屬於這個branch,此時你新建了branch2,並切換到了branch2上。 

(3) 此時你可以用 reset --keep 把在 start 之后的 commit 清除掉,但是保持 working tree 不變。


免責聲明!

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



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