可能說的不是很明白,就是我程式碼寫著寫著,發現我已經不想這麼弄了,用git reset --hard <版本號>
退回到之前的某個版本重寫,這樣當我寫完之後,想在提交到遠端倉庫,它就會報錯
To https://github.com/zifenggao/wenda.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'https://github.com/zifenggao/wenda.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
說我版本是之前的版本,要我合併後再提交,那我該怎麼弄,能了幾遍都沒搞懂。
首先,根據你的描述,既然你用到了
git reset --hard
,那就可以推斷出你已經add
和commit
過了。其次,根據報錯,可以推斷出你已經
push
過了(這個推斷基於只有你一個人擁有 master branch 的更改權限。那麼當你執行
git reset --hard
之後,歷史紀錄是不能跟遠端的記錄直接合併的。因此才會有這個報錯。舉個例子,遠端是
A -> B -> C -> D
,你git reset --hard
之後是A -> B
。這時候除非遠程那邊抹掉C
和D
,否則是不能合併的。因此,這時候,你應該使用
git push origin master --force
來強行覆蓋遠端記錄。請不要根據提示使用
git pull
。否則,你的本地又會變成A -> B -> C -> D
。因為git pull
相當於git fetch
+git merge
(以下內容基於上面的例子,遠端是
A -> B -> C -> D
,你想回滾到 B 那個狀態)樓上提到了
git revert
。其實,git reset --hard
和git revert
都可以實作「回滾程式碼」。但差別在於:git revert
會把你的本地變成A -> B -> C -> D -> E
。其中,E
幹的事兒是刪除C
和D
。這樣做的好處在於,你git push origin master
就不會有上面的報錯了。但,歷史線上還是會保留C
和D
這兩個 commit。如果使用這個指令,記得要add
然後commit
。git reset --hard
會直接刪除C
和D
,形成A -> B
這樣的結果。好處在於更直接更徹底。缺點在於,首先要透過git push origin master --force
去強行更改。其次,一旦你後悔了,除非根據本地的reflog
直接恢復 HEAD 指針,此外沒有其他辦法。用哪一個都是沒錯的,請依照自己的需求來選擇。
一般來說, 盡量避免這種情況.
如果你對遠端的master有權限, 可以這麼做:
更合理的做法是使用git revert
編輯分割線
另一位同學 @S1ngS1ng 答案更加詳細,但是拋出了一個觀點是用哪個都可以,這個我還是要重申下 git revert 才是更合適的姿勢
當是一個多人開發的場景,很有可能遠端的master上已經被其他人pull到了最新程式碼或合併到了其它分支,這種情況下reset將無效,因為對方仍然有可能push上來你這裡希望刪除的commit
所以這個用哪個都可以的觀點其實是有限定條件的