【问题标题】:Git pull after forced update强制更新后 Git 拉取
【发布时间】:2012-04-06 12:21:09
【问题描述】:

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

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

我需要类似于 git push --force 的反面,但 git pull --force 没有给出预期的结果。

【问题讨论】:

标签: git git-pull


【解决方案1】:

用变基拉动

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

git pull --rebase

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

git pull --rebase=interactive

或从 Git 2.26 开始可以缩短为:

git pull --rebase=i

【讨论】:

  • 我一直使用它来将最新代码从 master 获取到我的功能分支中,而无需将所有这些合并提交记录在历史记录中。
  • 这比git reset origin/master --hardgit rebase origin/master 简单得多,尤其是在没有本地提交的情况下。谢谢!
  • 谢谢!当我在 master 上重新定位我的功能分支时,这对我有用,强制推送它,然后 git pull --rebase d 它在另一台机器上。
  • 我没有调查过,但我认为这只有在添加新提交时才能正常工作——而不是删除或更改旧提交。 (比如说,如果一个分支重新基于另一个分支,或者提交的顺序发生了变化。)否则,您最终将重新添加已删除的提交。我认为这就是需要git reset的原因。
  • @NeilTraft 事实上,这就是为什么接受的答案包括交互模式下的变基。如果使用 rebase 退出,这也是可能的,所以我更新了我的答案。不需要重置(它是已接受答案中的两个选项之一)。
【解决方案2】:

单线解决方案

以下命令将拉取并强制更新

git pull --rebase

【讨论】:

    【解决方案3】:

    接收新的提交

    git fetch
    

    重置

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

    更改本地分支的提交:

    git reset origin/main --hard
    

    不过要小心,正如文档中所说的那样:

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

    如果您想真正在本地保留所做的任何更改 - 请改为使用 --soft 重置。这将更新分支的提交历史记录,但不会更改工作目录中的任何文件(然后您可以提交它们)。

    变基

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

    git rebase -i origin/main
    

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

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

    使用帮助git command --help 了解有关上述任何(或其他)命令的更多详细信息和示例。

    【讨论】:

    • @iblue 当你的同事使用 `git reabse origin/master' 时,同时他们之前已经有一些提交,git 会将你的提交写到他们提交的后面。
    • 可能值得一提的是,如果这是针对不同的分支:git reset origin/otherbranch --hard
    • 所以,澄清一下,这是或者:选项1:reset --hard选项2:reset --soft + rebase,对吗?
    • @PlasmaBinturong No. git reset --soft origin/master 将更改提交历史记录以匹配远程和阶段差异与远程然后提交。在那种情况下没有必要重新设置基准(并且由于未提交的更改,您将被阻止这样做),因为提交历史记录没有区别。这两个选项是 reset rebase - 不是两者的组合。如果您的情况与我在这里回答的不同,请ask a question
    • @bmaupin 先看看另一个分支!如果您想为任何分支选择选项 1,您必须先检查它。 git reset 将在您当前所在的任何分支上运行。
    【解决方案4】:

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

    git fetch
    

    重命名跟踪分支:

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

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

    git checkout -b <old-branch-name>
    

    【讨论】:

      【解决方案5】:

      这不会修复已经包含您不想要的代码的分支(请参阅下文了解如何执行此操作),但如果他们已经拉出一些分支并且现在希望它是干净的(而不是“原点/某个分支的前面),那么您只需:

      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:弗洛里安在评论中提到了这一点,但谁在寻找答案时会阅读 cmets?

      注意3:如果您有受污染的分支,您可以根据新的“哑分支”创建新的分支,然后只选择樱桃提交。

      例如:

      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
      

      现在新功能是您的分支,没有额外的(可能是坏的)提交!

      【讨论】:

      • 这是我真正想要的。有人重新设置了主分支(天知道是什么原因),但我没有想要提交的本地更改或任何东西。所以我所要做的就是删除我的本地主分支(感觉很奇怪)并再次结帐。谢谢!
      • @peter-mortensen 根据stackoverflow.com/help/editing,编辑应该是实质性的
      • 最后一步,也可以使用git checkout -b base-branch origin/base-branchgit checkout --track origin/base-branch
      猜你喜欢
      • 2020-01-16
      • 1970-01-01
      • 2012-03-03
      • 1970-01-01
      • 2014-01-16
      • 1970-01-01
      • 2011-05-31
      • 1970-01-01
      • 2020-09-16
      相关资源
      最近更新 更多