git 删除特定提交

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2938301/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 08:27:55  来源:igfitidea点击:

Remove specific commit

gitcommitrevertcherry-pick

提问by Joshua Cheek

I was working with a friend on a project, and he edited a bunch of files that shouldn't have been edited. Somehow I merged his work into mine, either when I pulled it, or when I tried to just pick the specific files out that I wanted. I've been looking and playing for a long time, trying to figure out how to remove the commits that contain the edits to those files, it seems to be a toss up between revert and rebase, and there are no straightforward examples, and the docs assume I know more than I do.

我和一个朋友一起做一个项目,他编辑了一堆不应该编辑的文件。不知何故,我将他的作品合并到我的作品中,无论是在我拉出它时,还是当我试图挑选出我想要的特定文件时。我一直在寻找和玩了很长时间,试图弄清楚如何删除包含对这些文件的编辑的提交,这似乎是在还原和变基之间折腾,并且没有简单的示例,并且文档假设我知道的比我多。

So here is a simplified version of the question:

所以这是问题的简化版本:

Given the following scenario, how do I remove commit 2?

鉴于以下情况,我如何删除提交 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(-)

The expected result is

预期的结果是

$ cat myfile
line 1
line 3

Here is an example of how I have been trying to revert

这是我如何尝试恢复的示例

$ 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.

采纳答案by Hal Eisen

The algorithm that Git uses when calculating diff's to be reverted requires that

Git 在计算要还原的差异时使用的算法要求

  1. the lines being reverted are not modified by any later commits.
  2. that there not be any other "adjacent" commits later in the history.
  1. 被恢复的行不会被任何后来的提交修改。
  2. 在历史后期没有任何其他“相邻”提交。

The definition of "adjacent" is based on the default number of lines from a context diff, which is 3. So if 'myfile' was constructed like this:

“相邻”的定义基于上下文差异的默认行数,即 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(-)

Then it all works as expected.

然后一切都按预期进行。

The second answer was very interesting. There is a feature which has not yet been officially released (though it is available in Git v1.7.2-rc2) called Revert Strategy. You can invoke git like this:

第二个答案很有趣。有一个尚未正式发布的功能(尽管它在 Git v1.7.2-rc2 中可用),称为 Revert Strategy。你可以像这样调用 git:

git revert --strategy resolve<commit>

git revert --strategy resolve<commit>

and it should do a better job figuring out what you meant. I do not know what the list of available strategies is, nor do I know the definition of any strategy.

它应该能更好地理解你的意思。我不知道可用策略的列表是什么,也不知道任何策略的定义。

回答by gaborous

There are four ways of doing so:

有四种方法可以这样做:

  • Clean way, reverting but keep in log the revert:

    git revert --strategy resolve <commit>
    
  • Harsh way, remove altogether only the last commit:

    git reset --soft "HEAD^"
    
  • 干净的方式,还原但保留日志还原:

    git revert --strategy resolve <commit>
    
  • 严厉的方式,只删除最后一次提交:

    git reset --soft "HEAD^"
    

Note: Avoid git reset --hardas it will also discard all changes in files since the last commit. If --softdoes not work, rather try --mixedor --keep.

注意:避免,git reset --hard因为它还会丢弃自上次提交以来文件中的所有更改。如果--soft不起作用,请尝试--mixed--keep

  • Rebase (show the log of the last 5 commits and delete the lines you don't want, or reorder, or squash multiple commits in one, or do anything else you want, this is a very versatile tool):

    git rebase -i HEAD~5
    
  • Rebase(显示最近 5 次提交的日志并删除您不想要的行,或重新排序,或将多个提交合并为一个,或做任何您想做的事情,这是一个非常通用的工具):

    git rebase -i HEAD~5
    

And if a mistake is made:

如果犯了错误:

git rebase --abort
  • Quick rebase: remove only a specific commit using its id:

    git rebase --onto commit-id^ commit-id
    
  • Alternatives: you could also try:

    git cherry-pick commit-id
    
  • Yet another alternative:

    git revert --no-commit
    
  • As a last resort, if you need full freedom of history editing (eg, because git don't allow you to edit what you want to), you can use this very fastopen source application: reposurgeon.

  • 快速变基:仅使用其 id 删除特定提交:

    git rebase --onto commit-id^ commit-id
    
  • 替代方案:您也可以尝试:

    git cherry-pick commit-id
    
  • 还有一个选择:

    git revert --no-commit
    
  • 作为最后的手段,如果您需要完全自由的历史编辑(例如,因为 git 不允许您编辑您想要的内容),您可以使用这个非常快速的开源应用程序:reposurgeon

Note: of course, all these changes are done locally, you should git pushafterwards to apply the changes to the remote. And in case your repo doesn't want to remove the commit ("no fast-forward allowed", which happens when you want to remove a commit you already pushed), you can use git push -fto force push the changes.

注意:当然,所有这些更改都是在本地完成的,git push之后您应该将更改应用于远程。如果您的存储库不想删除提交(“不允许快进”,当您想要删除已经推送的提交时会发生这种情况),您可以使用git push -f强制推送更改。

Note2: if working on a branch and you need to force push, you should absolutely avoid git push --forcebecause this may overwrite other branches (if you have made changes in them, even if your current checkout is on another branch). Prefer to always specify the remote branch when you force push: git push --force origin your_branch.

注意2:如果在一个分支上工作并且您需要强制推送,则绝对应该避免,git push --force因为这可能会覆盖其他分支(如果您对它们进行了更改,即使您当前的结帐在另一个分支上)。强制推送时,最好始终指定远程分支git push --force origin your_branch

回答by JD-V

Here is an easy solution:

这是一个简单的解决方案:

git rebase -i HEAD~x

(Note: xis the number of commits)

(注:x是提交次数)

upon executing notepad file will open. Enter dropbesides your commit.
If you don't know Vim, just click on each word pick that you want to edit and then hit the "I" key (for insert mode). Once you're done typing hit the "esc" key to exit insert mode.

执行记事本文件将打开。drop除了您的提交之外,请输入。
如果您不知道 Vim,只需单击您要编辑的每个单词选择,然后按“I”键(用于插入模式)。完成输入后,按“esc”键退出插入模式。



enter image description here



在此处输入图片说明

and that's it, you are done... Just sync the git dashboard and the changes will be pushed to remote.

就是这样,你完成了......只需同步 git 仪表板,更改将被推送到远程。

If the commit you drop was already on the remote, you will have to force push. Since --force is considered harmful, use git push --force-with-lease.

如果您删除的提交已经在遥控器上,您将不得不强制推送。由于 --force 被认为是 有害的,请使用git push --force-with-lease.

回答by Andrew Walker

Your choice is between

你的选择是

  1. keeping the error and introducing a fix and
  2. removing the error and changing the history.
  1. 保留错误并引入修复和
  2. 删除错误并更改历史记录。

You should choose (1) if the erroneous change has been picked up by anybody else and (2) if the error is limited to a private un-pushed branch.

您应该选择 (1) 如果错误的更改已被其他人发现,以及 (2) 如果错误仅限于私有的未推送分支。

Git revert is an automated tool to do (1), it creates a new commit undoing some previous commit. You'll see the error and removal in the project history but people who pull from your repository won't run into problems when they update. It's not working in an automated manner in your example so you need to edit 'myfile' (to remove line 2), do git add myfileand git committo deal with the conflict. You will then end up with four commits in your history, with commit 4 reverting commit 2.

Git revert 是一个自动化工具来做 (1),它创建一个新的提交来撤销之前的一些提交。您将在项目历史记录中看到错误和删除,但是从您的存储库中提取的人在更新时不会遇到问题。在您的示例中,它没有以自动方式工作,因此您需要编辑“myfile”(删除第 2 行),执行git add myfilegit commit处理冲突。然后你将在你的历史记录中得到四次提交,提交 4 恢复提交 2。

If nobody cares that your history changes, you can rewrite it and remove commit 2 (choice 2). The easy way to do this is to use git rebase -i 8230fa3. This will drop you into an editor and you can choose not to include the erroneous commit by removing the commit (and keeping "pick" next to the other commit messages. Do read up on the consequences of doing this.

如果没有人关心您的历史记录更改,您可以重写它并删除提交 2(选择 2)。做到这一点的简单方法是使用git rebase -i 8230fa3. 这将使您进入编辑器,您可以通过删除提交来选择不包含错误提交(并在其他提交消息旁边保留“pick”。请仔细阅读这样做后果

回答by tk_

Approch 1

接近 1

First get the commit hash(ex:1406cd61) that you need to revert. simple fix will be below command,

首先获取您需要还原的提交哈希(例如:1406cd61)。简单的修复将在命令下方,

$ git revert 1406cd61

if you have commit more changes related to 1406cd61 files after 1406cd61 commit, Above simple command will not work. Then you have to do the below steps, which is cherry picking.

如果您在 1406cd61 提交后提交了更多与 1406cd61 文件相关的更改,则上述简单命令将不起作用。然后你要做下面的步骤,这就是樱桃采摘。

Approch 2

接近 2

Please follow below squesnce of actions, Since we are using --force you need to have admin rightsover the git repo to do this.

请遵循以下操作顺序,由于我们正在使用 --force,因此您需要对git repo具有管理员权限才能执行此操作。

Step 1:Find the commit before the commit you want to remove git log

第 1 步:在要删除的提交之前找到该提交git log

Step 2:Checkout that commit git checkout <commit hash>

第 2 步:签出该提交git checkout <commit hash>

Step 3:Make a new branch using your current checkout commit git checkout -b <new branch>

第 3 步:使用您当前的结帐提交创建一个新分支git checkout -b <new branch>

Step 4:Now you need to add the commit after the removed commit git cherry-pick <commit hash>

第 4 步:现在您需要在删除的提交之后添加提交git cherry-pick <commit hash>

Step 5:Now repeat Step 4 for all other commits you want to keep.

第 5 步:现在对要保留的所有其他提交重复第 4 步。

Step 6:Once all commits have been added to your new branch and have been commited. Check that everything is in the correct state and working as intended. Double check everything has been commited: git status

第 6 步:将所有提交添加到新分支并提交后。检查一切是否处于正确状态并按预期工作。仔细检查所有内容是否已提交:git status

Step 7:Switch to your broken branch git checkout <broken branch>

第 7 步:切换到损坏的分支git checkout <broken branch>

Step 8:Now perform a hard reset on the broken branch to the commit prior to the one your want to remove git reset --hard <commit hash>

第 8 步:现在对损坏的分支执行硬重置到要删除的分支之前的提交git reset --hard <commit hash>

Step 9:Merge your fixed branch into this branch git merge <branch name>

第 9 步:将您的固定分支合并到此分支中git merge <branch name>

Step 10:Push the merged changes back to origin. WARNING: This will overwrite the remote repo! git push --force origin <branch name>

第 10 步:将合并的更改推回原点。警告:这将覆盖远程仓库!git push --force origin <branch name>

You can do the process without creating a new branch by replacing Step 2 & 3 with Step 8 then not carry out Step 7 & 9.

您可以通过将步骤 2 和 3 替换为步骤 8,然后不执行步骤 7 和 9,而无需创建新分支即可完成该过程。

回答by Dennis

You can remove unwanted commits with git rebase. Say you included some commits from a coworker's topic branch into your topic branch, but later decide you don't want those commits.

您可以使用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.

At this point your text editor will open the interactive rebase view. For example

此时,您的文本编辑器将打开交互式 rebase 视图。例如

git-rebase-todo

git-rebase-todo

  1. Remove the commits you don't want by deleting their lines
  2. Save and quit
  1. 通过删除它们的行来删除您不想要的提交
  2. 保存并退出

If the rebase wasn't successful, delete the temporary branch and try another strategy. Otherwise continue with the following instructions.

如果变基不成功,请删除临时分支并尝试另一种策略。否则,请继续执行以下说明。

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.

If you're pushing your topic branch to a remote, you may need to force push since the commit history has changed. If others are working on the same branch, give them a heads up.

如果您将主题分支推送到远程,您可能需要强制推送,因为提交历史已更改。如果其他人在同一个分支上工作,请提醒他们。

回答by sdaau

From other answers here, I was kind of confused with how git rebase -icould be used to remove a commit, so I hope it's OK to jot down my test case here (very similar to the OP).

从这里的其他答案中,我对如何git rebase -i删除提交感到困惑,所以我希望在这里记下我的测试用例是可以的(与 OP 非常相似)。

Here is a bashscript that you can paste in to create a test repository in the /tmpfolder:

这是一个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 [email protected]

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"

At this point, we have a file.txtwith these contents:

此时,我们有一个file.txt带有这些内容的:

aaaa
bbbb
cccc
dddd
eeee

At this point, HEAD is at the 5th commit, HEAD~1 would be the 4th - and HEAD~4 would be the 1st commit (so HEAD~5 wouldn't exist). Let's say we want to remove the 3rd commit - we can issue this command in the myrepo_gitdirectory:

此时, HEAD 处于第 5 次提交, HEAD~1 将是第 4 次 - HEAD~4 将是第 1 次提交(因此 HEAD~5 将不存在)。假设我们要删除第三次提交 - 我们可以在myrepo_git目录中发出此命令:

git rebase -i HEAD~4

(Note that git rebase -i HEAD~5results with "fatal: Needed a single revision; invalid upstream HEAD~5".) A text editor (see screenshot in @Dennis' answer) will open with these contents:

请注意,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
# ...

So we get all commits since(but not including) our requested HEAD~4. Delete the line pick 448c212 3rd git commitand save the file; you'll get this response from git rebase:

所以我们得到了(但不包括)我们请求的 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

At this point open myrepo_git/folder/file.txtin a text editor; you'll see it has been modified:

此时folder/file.txt在文本编辑器中打开 myrepo_git/ ;你会看到它已被修改:

aaaa
bbbb
<<<<<<< HEAD
=======
cccc
dddd
>>>>>>> b50213c... 4th git commit

Basically, gitsees that when HEAD got to 2nd commit, there was content of aaaa+ bbbb; and then it has a patch of added cccc+ddddwhich it doesn't know how to append to the existing content.

基本上,git看到当 HEAD 进行第二次提交时,有aaaa+ 的内容bbbb;然后它有一个添加的cccc+补丁dddd,它不知道如何附加到现有内容。

So here gitcannot decide for you - it is youwho has to make a decision: by removing the 3rd commit, you either keep the changes introduced by it (here, the line cccc) -- or you don't. If you don't, simply remove the extra lines - including the cccc- in folder/file.txtusing a text editor, so it looks like this:

所以这里git不能为你做决定——必须做出决定:通过删除第 3 次提交,你要么保留它引入的更改(这里是行cccc)——或者你不保留。如果不这样做,只需使用文本编辑器删除多余的行 - 包括cccc- folder/file.txt,它看起来像这样:

aaaa
bbbb
dddd

... and then save folder/file.txt. Now you can issue the following commands in myrepo_gitdirectory:

...然后保存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

Ah - so in order to mark that we've solved the conflict, we mustgit addthe folder/file.txt, before doing git rebase --continue:

啊-所以为了标记,我们已经解决了这个矛盾,我们必须git addfolder/file.txt,在做之前git rebase --continue

$ git add folder/file.txt
$ git rebase --continue

Here a text editor opens again, showing the line 4th git commit- here we have a chance to change the commit message (which in this case could be meaningfully changed to 4th (and removed 3rd) commitor similar). Let's say you don't want to - so just exit the text editor without saving; once you do that, you'll get:

这里再次打开一个文本编辑器,显示该行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.

At this point, now you have a history like this (which you could also inspect with say gitk .or other tools) of the contents of folder/file.txt(with, apparently, unchanged timestamps of the original commits):

在这一点上,现在您有这样的历史记录(您也可以使用 saygitk .或其他工具检查)内容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

And if previously, we decided to keep the line cccc(the contents of the 3rd git commit that we removed), we would have had:

如果之前我们决定保留该行cccc(我们删除的第 3 个 git commit 的内容),我们将拥有:

1st git commit  |  +aaaa
----------------------------------------------
2nd git commit  |   aaaa
                |  +bbbb
----------------------------------------------
4th git commit  |   aaaa
                |   bbbb
                |  +cccc
                |  +dddd
----------------------------------------------
5th git commit  |   aaaa
                |   bbbb
                |   cccc
                |   dddd
                |  +eeee

Well, this was the kind of reading I hoped I'd have found, to start grokking how git rebaseworks in terms of deleting commits/revisions; so hope it might help others too...

嗯,这是我希望我能找到的那种阅读方式,开始了解git rebase删除提交/修订的工作原理;所以希望它也可以帮助其他人......

回答by Cascabel

So it sounds like the bad commit was incorporated in a merge commit at some point. Has your merge commit been pulled yet? If yes, then you'll want to use git revert; you'll have to grit your teeth and work through the conflicts. If no, then you could conceivably either rebase or revert, but you can do so beforethe merge commit, then redo the merge.

因此,这听起来像是在某个时候将错误提交合并到了合并提交中。你的合并提交被拉了吗?如果是,那么您将要使用git revert; 你必须咬紧牙关,解决冲突。如果不是,那么您可以想象变基或还原,但您可以在合并提交之前这样做,然后重做合并。

There's not much help we can give you for the first case, really. After trying the revert, and finding that the automatic one failed, you have to examine the conflicts and fix them appropriately. This is exactly the same process as fixing merge conflicts; you can use git statusto see where the conflicts are, edit the unmerged files, find the conflicted hunks, figure out how to resolve them, add the conflicted files, and finally commit. If you use git commitby itself (no -m <message>), the message that pops up in your editor should be the template message created by git revert; you can add a note about how you fixed the conflicts, then save and quit to commit.

对于第一种情况,我们真的无法为您提供太多帮助。尝试还原后,发现自动还原失败,您必须检查冲突并适当修复它们。这与修复合并冲突的过程完全相同;您可以使用git status查看冲突在哪里,编辑未合并的文件,找到冲突的大块头,弄清楚如何解决它们,添加冲突的文件,最后提交。如果您单独使用git commit(no -m <message>),则在您的编辑器中弹出的消息应该是由git revert;创建的模板消息;您可以添加有关如何修复冲突的注释,然后保存并退出以提交。

For the second case, fixing the problem beforeyour merge, there are two subcases, depending on whether you've done more work since the merge. If you haven't, you can simply git reset --hard HEAD^to knock off the merge, do the revert, then redo the merge. But I'm guessing you have. So, you'll end up doing something like this:

对于第二种情况,合并之前解决问题,有两个子情况,这取决于您是否在合并后做了更多的工作。如果还没有,您可以简单git reset --hard HEAD^地取消合并,进行还原,然后重做合并。但我猜你有。所以,你最终会做这样的事情:

  • create a temporary branch just before the merge, and check it out
  • do the revert (or use git rebase -i <something before the bad commit> <temporary branch>to remove the bad commit)
  • redo the merge
  • rebase your subsequent work back on: git rebase --onto <temporary branch> <old merge commit> <real branch>
  • remove the temporary branch
  • 在合并之前创建一个临时分支,并检查它
  • 执行还原(或用于git rebase -i <something before the bad commit> <temporary branch>删除错误提交)
  • 重做合并
  • 重新将您的后续工作重新建立在: git rebase --onto <temporary branch> <old merge commit> <real branch>
  • 删除临时分支

回答by Frans

So you did some work and pushed it, lets call them commits A and B. Your coworker did some work as well, commits C And D. You merged your coworkers work into yours (merge commit E), then continued working, committed that, too (commit F), and discovered that your coworker changed some things he shouldn't have.

所以你做了一些工作并推送它,让他们称之为提交 A 和 B。你的同事也做了一些工作,提交 C 和 D。你将你同事的工作合并到你的工作中(合并提交 E),然后继续工作,承诺,也是(提交 F),并发现您的同事更改了一些他不应该更改的内容。

So your commit history looks like this:

所以你的提交历史看起来像这样:

A -- B -- C -- D -- D' -- E -- F

You really want to get rid of C, D, and D'. Since you say you merged your coworkers work into yours, these commits already "out there", so removing the commits using e.g. git rebase is a no-no. Believe me, I've tried.

你真的想摆脱 C、D 和 D'。由于您说您将同事的工作合并到您的工作中,因此这些提交已经“在那里”,因此使用例如 git rebase 删除提交是禁忌。相信我,我已经试过了。

Now, I see two ways out:

现在,我看到了两种出路:

  • if you haven't pushed E and F to your coworker or anyone else (typically your "origin" server) yet, you could still remove those from the history for the time being. This is your work that you want to save. This can be done with a

    git reset D'
    

    (replace D' with the actual commit hash that you can obtain from a git log

    At this point, commits E and F are gone and the changes are uncommitted changes in your local workspace again. At this point I would move them to a branch or turn them into a patch and save it for later. Now, revert your coworker's work, either automatically with a git revertor manually. When you've done that, replay your work on top of that. You may have merge conflicts, but at least they'll be in the code youwrote, instead of your coworker's code.

  • If you've already pushed the work you did after your coworker's commits, you can still try and get a "reverse patch" either manually or using git revert, but since your work is "in the way", so to speak you'll probably get more merge conflicts and more confusing ones. Looks like that's what you ended up in...

  • 如果您还没有将 E 和 F 推送给您的同事或其他任何人(通常是您的“原始”服务器),您仍然可以暂时从历史记录中删除它们。这是您要保存的工作。这可以通过

    git reset D'
    

    (将 D' 替换为您可以从 git log

    此时,提交 E 和 F 消失了,更改再次成为本地工作区中未提交的更改。在这一点上,我会将它们移动到一个分支或将它们变成一个补丁并保存以备后用。现在,使用 自动git revert或手动还原您同事的工作。完成后,在此基础上重播您的工作。您可能会遇到合并冲突,但至少它们会出现在编写的代码中,而不是您同事的代码中。

  • 如果您已经在同事提交后推送了您所做的工作,您仍然可以尝试手动或使用“反向补丁” git revert,但由于您的工作“碍手碍脚”,可以这么说,您可能会得到更多的合并冲突和更令人困惑的冲突。看起来这就是你最终的结果......

回答by ShaDow RiDeR

git revert --strategy resolve if commit is a merge:use git revert --strategy resolve -m 1

混帐复归--strategy决心 ,如果提交的是一个合并:使用git复归--strategy决心-m 1