我刚刚用git rebase压缩了一些提交,并做了一个git push——force(这是邪恶的,我知道)。

现在其他软件工程师有不同的历史,当他们进行git pull时,git会合并。有没有办法解决这个问题,除了做一个rm my-repo;Git克隆git@example.org:my-repo.git?

我需要一些与git push -force相反的东西,但是git pull -force没有给出预期的结果。


接收新的提交

git fetch

重置

你可以使用git reset重置本地分支的提交。

修改本地分支的提交。

git reset origin/main --hard

但是要小心,正如文档所说:

重置索引和工作树。自<commit>以来对工作树中跟踪文件的任何更改都将被丢弃。

如果你想要保留你在本地所做的任何更改-做一个-软重置。它将更新分支的提交历史,但不会更改工作目录中的任何文件(然后您可以提交它们)。

变基

你可以使用git rebase在任何其他提交/分支上重播你的本地提交:

git rebase -i origin/main

这将在交互模式下调用rebase,在这种模式下,您可以选择如何应用不在您所基于的历史记录中的每个单独的提交。

如果你删除的提交(使用git push -f)已经被拉到本地历史中,它们将被列为将被重新应用的提交——它们需要作为rebase的一部分被删除,或者它们将被简单地重新包含到分支的历史中——并在下一次推送时重新出现在远程历史中。

使用help git命令——help获取更多关于上述(或其他)命令的详细信息和示例。


这不会修复已经有你不想要的代码的分支(参见下面如何做),但如果他们已经拉了一些分支,现在想要它是干净的(而不是“在原点/一些分支之前”),那么你只需:

git checkout some-branch   # where some-branch can be replaced by any other branch
git branch base-branch -D  # where base-branch is the one with the squashed commits
git checkout -b base-branch origin/base-branch  # recreating branch with correct commits

注意:你可以通过在它们之间加上&&来组合它们

注2:弗洛里安在评论中提到了这一点,但谁会在寻找答案时阅读评论呢?

注3:如果您有被污染的分支,您可以基于新的“愚蠢的分支”创建新的分支,然后选择提交。

Ex:

git checkout feature-old  # some branch with the extra commits
git log                   # gives commits (write down the id of the ones you want)
git checkout base-branch  # after you have already cleaned your local copy of it as above
git checkout -b feature-new # make a new branch for your feature
git cherry-pick asdfasd   # where asdfasd is one of the commit ids you want
# repeat previous step for each commit id
git branch feature-old -D # delete the old branch

现在feature-new是没有额外(可能是坏的)提交的分支!


用rebase拉

常规的pull是fetch + merge,但你想要的是fetch + rebase。这是一个pull命令的选项:

git pull --rebase

在您的特定情况下,您不希望重新应用的提交已被删除。这必须手动完成。因此,rebase需要是交互式的,这样可以跳过这些提交:

git pull --rebase=interactive

或者从Git 2.26开始可以缩写为:

git pull --rebase=i

从远程存储库获取更改到本地repo:

git fetch

重命名跟踪分支:

git branch -m <old-branch-name> <new-name>

创建一个新的本地分支跟踪远程分支:

git checkout -b <old-branch-name>