Jos*_*eek 260 git commit revert cherry-pick
我和一位朋友在一个项目上合作,他编辑了一堆本不应该编辑过的文件.不知怎的,我将他的作品合并到了我的作品中,或者当我拉动它时,或者当我试图选择我想要的特定文件时.我一直在寻找和玩很长一段时间,试图弄清楚如何删除包含对这些文件的编辑的提交,它似乎是revert和rebase之间的折腾,并没有简单的例子,并且docs假设我比我知道的更多.
所以这是问题的简化版本:
鉴于以下情况,如何删除提交2?
$ mkdir git_revert_test && cd git_revert_test
$ git init
Initialized empty Git repository in /Users/josh/deleteme/git_revert_test/.git/
$ echo "line 1" > myfile
$ git add -A
$ git commit -m "commit 1"
[master (root-commit) 8230fa3] commit 1
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 myfile
$ echo "line 2" >> myfile
$ git commit -am "commit 2"
[master 342f9bb] commit 2
1 files changed, 1 insertions(+), 0 deletions(-)
$ echo "line 3" >> myfile
$ git commit -am "commit 3"
[master 1bcb872] commit 3
1 files changed, 1 insertions(+), 0 deletions(-)
Run Code Online (Sandbox Code Playgroud)
预期的结果是
$ cat myfile
line 1
line 3
Run Code Online (Sandbox Code Playgroud)
这是我一直试图恢复的一个例子
$ git revert 342f9bb
Automatic revert failed. After resolving the conflicts,
mark the corrected paths with 'git add <paths>' or 'git rm <paths>'
and commit the result.
Run Code Online (Sandbox Code Playgroud)
gab*_*ous 257
有四种方法:
干净的方式,恢复但保持在日志恢复:
git revert --strategy resolve <commit>
Run Code Online (Sandbox Code Playgroud)苛刻的方式,完全删除最后一次提交:
git reset --soft "HEAD^"
Run Code Online (Sandbox Code Playgroud)注意:避免,git reset --hard因为它也会丢弃自上次提交以来文件中的所有更改.如果--soft不起作用,请尝试--mixed或--keep.
Rebase(显示最近5次提交的日志并删除你不想要的行,或重新排序,或者将多个提交压缩成一个,或者做任何你想做的事情,这是一个非常通用的工具):
git rebase -i HEAD~5
Run Code Online (Sandbox Code Playgroud)如果出现错误:
git rebase --abort
Run Code Online (Sandbox Code Playgroud)
快速rebase:使用其id仅删除特定提交:
git rebase --onto commit-id^ commit-id
Run Code Online (Sandbox Code Playgroud)替代方案:您也可以尝试:
git cherry-pick commit-id
Run Code Online (Sandbox Code Playgroud)另一种选择:
git revert --no-commit
Run Code Online (Sandbox Code Playgroud)作为最后的手段,如果你需要完全自由的历史编辑(例如,因为git不允许你编辑你想要的东西),你可以使用这个非常快速的开源应用程序:reposurgeon.
注意:当然,所有这些更改都是在本地完成的,git push之后您应该将更改应用到远程.如果您的repo不想删除提交("不允许快进",当您想删除已经推送的提交时会发生这种情况),您可以使用git push -f强制推送更改.
注意2:如果在分支上工作而你需要强制推送,你应该绝对避免,git push --force因为这可能会覆盖其他分支(如果你已经对它们进行了更改,即使你当前的结账在另一个分支上).强制推送时,首选指定远程分支:git push --force origin your_branch.
Hal*_*sen 63
Git在计算要回复的差异时使用的算法需要这样做
"相邻"的定义基于上下文差异的默认行数,即3.如果'myfile'构造如下:
$ cat >myfile <<EOF
line 1
junk
junk
junk
junk
line 2
junk
junk
junk
junk
line 3
EOF
$ git add myfile
$ git commit -m "initial check-in"
1 files changed, 11 insertions(+), 0 deletions(-)
create mode 100644 myfile
$ perl -p -i -e 's/line 2/this is the second line/;' myfile
$ git commit -am "changed line 2 to second line"
[master d6cbb19] changed line 2
1 files changed, 1 insertions(+), 1 deletions(-)
$ perl -p -i -e 's/line 3/this is the third line/;' myfile
$ git commit -am "changed line 3 to third line"
[master dd054fe] changed line 3
1 files changed, 1 insertions(+), 1 deletions(-)
$ git revert d6cbb19
Finished one revert.
[master 2db5c47] Revert "changed line 2"
1 files changed, 1 insertions(+), 1 deletions(-)
Run Code Online (Sandbox Code Playgroud)
然后一切按预期工作.
第二个答案非常有趣.有一个功能尚未正式发布(虽然它在Git v1.7.2-rc2中可用)称为Revert Strategy.你可以像这样调用git:
git revert --strategy resolve <commit>
它应该做得更好,弄清楚你的意思.我不知道可用策略列表是什么,也不知道任何策略的定义.
And*_*ker 36
你的选择介于
您应该选择(1)其他人是否已接收到错误更改,以及(2)如果错误仅限于私人未推送分支.
Git revert是一个自动化的工具(1),它创建一个新的提交撤消一些先前的提交.您将在项目历史记录中看到错误和删除,但从存储库中提取的人员在更新时不会遇到问题.它在您的示例中不是以自动方式工作,因此您需要编辑"myfile"(删除第2行),执行git add myfile并git commit处理冲突.然后,您将在历史记录中进行四次提交,其中commit 4将还原提交2.
如果没有人关心您的历史记录发生变化,您可以重写它并删除提交2(选择2).这样做的简单方法是使用git rebase -i 8230fa3.这将使您进入编辑器,您可以选择不通过删除提交来包含错误提交(并在其他提交消息旁边保留"选择".请阅读执行此操作的后果.
tk_*_*tk_ 23
请遵循以下的操作步骤,因为我们使用--force,您需要拥有git repo的管理员权限才能执行此操作.
步骤1:在要删除的提交之前查找提交git log
第2步:签出提交git checkout <commit hash>
第3步:使用当前的结帐提交创建一个新分支git checkout -b <new branch>
第4步:现在您需要在删除提交后添加提交git cherry-pick <commit hash>
步骤5:现在对要保留的所有其他提交重复步骤4.
步骤6:将所有提交添加到新分支并提交后.检查一切是否处于正确状态并按预期工作.仔细检查一切已经提交:git status
第7步:切换到破碎的分支git checkout <broken branch>
步骤8:现在在要删除的分支之前对已损坏的分支执行硬重置git reset --hard <commit hash>
第9步:将固定分支合并到此分支中git merge <branch name>
步骤10:将合并的更改推回原点.警告:这将覆盖远程仓库!git push --force origin <branch name>
您可以在不创建新分支的情况下执行此过程,方法是将步骤2和3替换为步骤8,然后不执行步骤7和9.
Den*_*nis 17
您可以删除不需要的提交git rebase.假设您从同事的主题分支包含一些提交到您的主题分支,但后来决定您不希望这些提交.
git checkout -b tmp-branch my-topic-branch # Use a temporary branch to be safe.
git rebase -i master # Interactively rebase against master branch.
Run Code Online (Sandbox Code Playgroud)
此时,文本编辑器将打开交互式rebase视图.例如

如果rebase不成功,请删除临时分支并尝试其他策略.否则,请继续以下说明.
git checkout my-topic-branch
git reset --hard tmp-branch # Overwrite your topic branch with the temp branch.
git branch -d tmp-branch # Delete the temporary branch.
Run Code Online (Sandbox Code Playgroud)
如果您将主题分支推送到远程,则可能需要强制推送,因为提交历史记录已更改.如果其他人在同一个分支机构工作,请给他们一个抬头.
从这里的其他答案,我有点混淆如何git rebase -i用于删除提交,所以我希望在这里记下我的测试用例(非常类似于OP).
这是一个bash可以粘贴的脚本,用于在/tmp文件夹中创建测试存储库:
set -x
rm -rf /tmp/myrepo*
cd /tmp
mkdir myrepo_git
cd myrepo_git
git init
git config user.name me
git config user.email me@myself.com
mkdir folder
echo aaaa >> folder/file.txt
git add folder/file.txt
git commit -m "1st git commit"
echo bbbb >> folder/file.txt
git add folder/file.txt
git commit -m "2nd git commit"
echo cccc >> folder/file.txt
git add folder/file.txt
git commit -m "3rd git commit"
echo dddd >> folder/file.txt
git add folder/file.txt
git commit -m "4th git commit"
echo eeee >> folder/file.txt
git add folder/file.txt
git commit -m "5th git commit"
Run Code Online (Sandbox Code Playgroud)
在这一点上,我们有file.txt这些内容:
aaaa
bbbb
cccc
dddd
eeee
Run Code Online (Sandbox Code Playgroud)
此时,HEAD处于第5次提交,HEAD~1将是第4次 - 而HEAD~4将是第1次提交(因此HEAD~5将不存在).假设我们要删除第3次提交 - 我们可以在myrepo_git目录中发出以下命令:
git rebase -i HEAD~4
Run Code Online (Sandbox Code Playgroud)
(请注意,git rebase -i HEAD~5结果为"致命:需要单个修订;无效的上游HEAD~5".)文本编辑器(请参阅@Dennis'答案中的屏幕截图)将打开以下内容:
pick 5978582 2nd git commit
pick 448c212 3rd git commit
pick b50213c 4th git commit
pick a9c8fa1 5th git commit
# Rebase b916e7f..a9c8fa1 onto b916e7f
# ...
Run Code Online (Sandbox Code Playgroud)
所以,我们得到了所有的提交,因为(但不包括)我们要求HEAD〜4.删除该行pick 448c212 3rd git commit并保存该文件; 你会得到这样的回应git rebase:
error: could not apply b50213c... 4th git commit
When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".
Could not apply b50213c... 4th git commit
Run Code Online (Sandbox Code Playgroud)
此时folder/file.txt在文本编辑器中打开myrepo_git/; 你会看到它已被修改:
aaaa
bbbb
<<<<<<< HEAD
=======
cccc
dddd
>>>>>>> b50213c... 4th git commit
Run Code Online (Sandbox Code Playgroud)
基本上,git看到当HEAD进入第二次提交时,有aaaa+的内容bbbb; 然后它有一个添加cccc+ 的补丁dddd,它不知道如何附加到现有内容.
因此,这里git无法为您做出决定 - 您需要做出决定:通过删除第3次提交,您可以保留其引入的更改(此处为行cccc) - 或者您不这样做.如果不这样做,只需删除额外的行 - 包括cccc- folder/file.txt使用文本编辑器,所以它看起来像这样:
aaaa
bbbb
dddd
Run Code Online (Sandbox Code Playgroud)
......然后保存folder/file.txt.现在,您可以在myrepo_git目录中发出以下命令:
$ nano folder/file.txt # text editor - edit, save
$ git rebase --continue
folder/file.txt: needs merge
You must edit all merge conflicts and then
mark them as resolved using git add
Run Code Online (Sandbox Code Playgroud)
啊-所以为了纪念,我们已经解决了这个矛盾,我们必须 git add在folder/file.txt,在做之前git rebase --continue:
$ git add folder/file.txt
$ git rebase --continue
Run Code Online (Sandbox Code Playgroud)
这里再次打开一个文本编辑器,显示该行4th git commit- 这里我们有机会更改提交消息(在这种情况下可以有意义地更改为4th (and removed 3rd) commit或类似).假设您不想 - 只需退出文本编辑器而不保存; 一旦你这样做,你会得到:
$ git rebase --continue
[detached HEAD b8275fc] 4th git commit
1 file changed, 1 insertion(+)
Successfully rebased and updated refs/heads/master.
Run Code Online (Sandbox Code Playgroud)
此时,现在您有一个这样的历史记录(您也可以使用说法gitk .或其他工具检查)的内容folder/file.txt(显然,原始提交的时间戳保持不变):
1st git commit | +aaaa
----------------------------------------------
2nd git commit | aaaa
| +bbbb
----------------------------------------------
4th git commit | aaaa
| bbbb
| +dddd
----------------------------------------------
5th git commit | aaaa
| bbbb
| dddd
| +eeee
Run Code Online (Sandbox Code Playgroud)
如果以前,我们决定保留该行cccc(我们删除的第3个git提交的内容),我们会有:
1st git commit | +aaaa
----------------------------------------------
2nd git commit | aaaa
| +bbbb
----------------------------------------------
4th git commit | aaaa
| bbbb
| +cccc
| +dddd
----------------------------------------------
5th git commit | aaaa
| bbbb
| cccc
| dddd
| +eeee
Run Code Online (Sandbox Code Playgroud)
嗯,这是我希望我已经找到的那种阅读,开始了解如何git rebase删除提交/修订; 所以希望它也可以帮助别人......