標籤:

Git 手欠恢復技巧

翻譯自 Git Out Of Trouble。

搭建練習環境

  1. Github.com 上創建倉庫並 clone 到本地;

  2. 創建一個新分支,叫作 test;

  3. 創建一系列 commit,可使用如下腳本:

    • Bash

    for d in {1..6};n do touch file$d.md;n git add file$d.md;n git commit -m "adding file $d";n donen

    • PowerShell

    for ($d=1; $d -le 6;$d++) {n touch file$d.md;n git add file$d.md;n git commit -m "adding file$d.md";n }n

創建了太多細碎的 Commit

在開發自己的項目的過程中,可能很多細小的改變也創建了 commit,這使得 commit 歷史很繁瑣。

還沒有 push

如果還沒有 push, 可以修改創建的 commit 而無需擔心在和協作者開發時出現問題。

  1. 確保當前分支正確,並輸入命令 git log --oneline;

  2. 在本例中,我們將 adding files 4, 5, and 6 的 commit 合併。所以找到 adding file 3 的 commit 的 SHA-1 值;

  3. 輸入命令 git reset --soft SHA-1,其中 SHA-1 為 adding file 3 的 SHA-1;

  4. 輸入 git status,將會看到 files 4, 5, 6;

  5. 輸入 git commit -m "Adding files 4, 5, and 6";

  6. 輸入 git log --oneline,此時 commit 歷史已經修改完成。

已經 push 了

此時再通過 Git 修改 commit 將可能會引起協作上的問題,所以建議使用 Squash and Merge 來修改。

翔一樣的 Commit Message

比如單詞寫錯了,寫了不該寫的東西之類的情況。

還沒有 push

首先問自己一個問題,是要修改上一個 commit 還是要修改之前的幾個 commits?

修改上一個 commit

  1. 確認在正確的分支;

  2. 輸入 git log --oneline 來確定你想要修改的 commit 在列表的最上面;

  3. 輸入 git commit --amend;

  4. 輸入你想要修改的 message。

修改之前的 commit

  1. 確認分支並輸入 git log --oneline;

  2. 找到你想要修改的 commit 的前一個 SHA-1,在本例中,使用 add file 4;

  3. 輸入 git reset --mixed SHA-1;

  4. 現在可以重新 add 和 commit 對 file 5 和 6 的修改了。

已經 push 了

此時需要使用 git push --force-with-lease 命令,該命令可能會對協作者造成嚴重的問題,如果 message 不是那麼爛,可以考慮就那樣放著。

首先問自己一個問題,是要修改上一個 commit 還是要修改之前的幾個 commits?

修改上一個 commit

  1. 確認在正確的分支;

  2. 輸入 git log --oneline 來確定你想要修改的 commit 在列表的最上面;

  3. 輸入 git commit --amend;

  4. 輸入你想要修改的 message;

  5. 輸入 git push --force-with-lease 強行向 remote 同步更改。

修改之前的 commit

  1. 確認分支並輸入 git log --oneline;

  2. 找到你想要修改的 commit 的前一個 SHA-1,在本例中,使用 add file 4;

  3. 輸入 git rebase -i SHA-1,-i 是使用交互模式,會打開編輯器,讓你更改 rebase 腳本;

  4. 找到你想要修改的 commit,將 pick 替換為 e 或是 edit,當更改完成後關閉編輯器,回到終端;

  5. rebase 操作會停在第一個被編輯的 commit 處,輸入 git commit --amend 修改該 commit message;

  6. 關閉編輯器,輸入 git rebase --continue;

  7. 重複前兩步操作;

  8. 當全部 commit 修改完,輸入 git push --force-with-lease。

提交到了錯誤的分支

突然發現提交到了 master 分支而不是用來開發的分支。

還沒有 push

  1. 確認現在處於提交錯誤 commit 的分支,在本例中,已經提交了幾個 commits 在 test 分支中;

  2. 輸入 git log --oneline,找到錯誤 commit 之前的一個 SHA-1 值,本例中,假定 file 5 本來應該提交到另一個分支上;

  3. 輸入 git reset --mixed SHA-1,其中 SHA-1 為 adding file 4 的 SHA-1;

  4. 輸入 git status,此時 file 5 和 6 都在工作目錄中;

  5. 輸入 git checkout -b correct,創建一個名為 correct 的新分支並檢出;

  6. 輸入 git status,此時 file 5 和 6 應該還在工作目錄中;

  7. 添加 file 5 和 6,git add file*;

  8. 輸入 git status,現在 file 5 和 6 已被成功添加,等待 commit;

  9. 輸入 git commit -m "Adding file 5 and 6"。

已經 push 了

首要任務:將 master 分支修好

  1. 在 master 分支中輸入 git log --oneline,找到需要移除的 commits,在本例中,定為 adding file 3

  2. 輸入 git revert SHA-1,可以 revert 多個 commits,用空格分開;

  3. 修改 revert commit message,或者可以直接關閉編輯器;

  4. 輸入 git push。

重建分支

現在 master 分支已經修好,創建一個新分支來整理錯誤的 commits。

  1. 創建分支,git checkout -b new-branch,或者檢出到已創建好的分支;

  2. 輸入 git reflog,找到需要重建的 commits 的 SHA-1;

  3. 輸入 git cherry-pick SHA-1,可以重建多個 SHA-1 值,用空格分開;

  4. 輸入 git push -u origin new-branch。

意外 commit

還沒有 push

  1. 確認在正確的分支,並輸入 git log --oneline;

  2. 在本例中,假定我們並不想提交 file 6,所以找到 adding file 5 的 SHA-1;

  3. 輸入 git reset --mixed SHA-1;

  4. 輸入 git status,現在 file 6 將出現在工作目錄中。

已經 push 了

首先需要 revert commits。

  1. 確認在正確的分支,並輸入 git log --oneline;

  2. 找到錯誤的 commit 的 SHA-1,本例中,使用 adding file 4

  3. 輸入 git revert SHA-1;

  4. 輸入 revert message,或保留默認直接關閉編輯器;

  5. 輸入 git push。

恢復工作。

  1. 輸入 git log --oneline,找到 revert commit,如果是默認的,應該為 Revert "adding file 4";

  2. 輸入 git revert SHA-1,SHA-1值為 revert commit;

  3. 完成當前需要繼續的工作;

  4. 輸入 git add;

  5. 輸入 git commit --amend,將現在的修改合併到之前的 commit 中;

  6. 輸入正確的 commit message;

  7. 輸入 git push 同步工作。

推倒重來

還沒有 push

首先問自己一個問題:要徹底重來還是有一部分可以湊合留著?

徹底重來

  1. 檢出到 master 分支,git checkout master;

  2. 刪除舊分支,git branch -D BRANCH-NAME。

有一部分可以留著

如果你想看到一些炫酷的操作,請在文件瀏覽器中打開倉庫(Finder 等),然後放在能看到的地方。

  1. 確認在正確的分支,並輸入 git log --oneline;

  2. 找到你想要保留的最後一次 commit 的 SHA-1 值。在本例中,假定 file 1 和 2 是要保留的,其他部分不要,所以找到 adding file 2 的 SHA-1 值;

  3. 輸入 git reset --hard SHA-1,如果你打開了文件瀏覽器,你會發現已經出現了一些炫酷的操作!

  4. 輸入 git status 和 ls,注意到現在只有 file 1 和 2 仍保留著。

  5. 輸入 git log --oneline,adding file2.md 之後的 commits 都消失了。

等等,我好像幹了不該乾的事!

一時衝動,你「意外」地刪除了一些文件。

找回一個文件

  1. 輸入 git reflog;

  2. 找到 adding file 6 commit 的 SHA-1 值;

  3. 輸入 git cherry-pick SHA-1;

  4. 輸入 git log --oneline 和 ls,file 6 已經回來了。

全部找回

  1. 輸入 git reflog;

  2. 找到 adding file 6 commit 的 SHA-1 值;

  3. 輸入 git reset --hard SHA-1;

  4. 輸入 git log --oneline,所有文件都出現了。

已經 push 了

首先問自己一個問題:要徹底重來還是有一部分可以湊合留著?

徹底重來

  1. 檢出到 master 分支,git checkout master;

  2. 輸入 git push origin :BRANCH-NAME 或者 git push --delete BRANCH-NAME 來刪除遠程的分支;

  3. 輸入 git fetch --prune 來刪除遠程跟蹤分支;

  4. 輸入 git branch -D BRANCH-NAME 刪除分支的本地拷貝。

有一部分可以留著

  1. 確認在正確的分支,並輸入 git log --oneline;

  2. 找到你想要保留的最後一次 commit 的 SHA-1 值。在本例中,假定 file 1 和 2 是要保留的,其他部分不要,所以找到 adding file 2 的 SHA-1 值;

  3. 輸入 git reset --hard SHA-1;

  4. 輸入 git status 和 ls,注意到現在只有 file 1 和 2 仍保留著;

  5. 輸入 git push --force。

推薦閱讀:

面向對象與函數式編程做對了什麼?
提醒:別睡了,起來學習吧(cs61a,cs61b Sp18開課了)
暫時不會再寫關於 Kotlin 的東西了
PHP 7 新特性(完結篇)

TAG:Git | 编程 |