MENU

Git 手欠恢复技巧

June 28, 2017 • Read: 3941 • 代码

翻译自 Git Out Of Trouble

搭建练习环境

  1. 在 Github.com 上创建仓库并 clone 到本地;
  2. 创建一个新分支,叫作 test
  3. 创建一系列 commit,可使用如下脚本:

    • Bash

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

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

创建了太多细碎的 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 statusls,注意到现在只有 file 1 和 2 仍保留着。
  5. 输入 git log --onelineadding file2.md 之后的 commits 都消失了。

等等,我好像干了不该干的事!

一时冲动,你「意外」地删除了一些文件。

找回一个文件

  1. 输入 git reflog
  2. 找到 adding file 6 commit 的 SHA-1 值;
  3. 输入 git cherry-pick SHA-1
  4. 输入 git log --onelinels,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 statusls,注意到现在只有 file 1 和 2 仍保留着;
  5. 输入 git push --force
Last Modified: June 29, 2017
Archives QR Code
QR Code for this page
Tipping QR Code