在git中,在拉操作之后编辑历史预拉操作提交会导致与源代码的差异

在git中,在拉操作之后编辑历史预拉操作提交会导致与源代码的差异,git,rebase,Git,Rebase,在以下场景中: 做一个A,B,C 拉 进行更多的提交F、G、H 意识到你需要调整B 使用git-rebase-i和git-commit-amend调整B 现在,git status显示: Your branch and 'origin/master' have diverged. 我该如何解决这个问题 注意:我没有推;这与推动无关 注意:简单地再次拉动并不能解决问题;它只是在我已有的基础上重新合并了提交的D,E(尽管D,E在历史上已经存在),这也会产生产生多余冲突的副作用 下面的一个答案表明,

在以下场景中:

  • 做一个A,B,C
  • 进行更多的提交F、G、H
  • 意识到你需要调整B
  • 使用
    git-rebase-i
    git-commit-amend调整B
  • 现在,
    git status
    显示:

    Your branch and 'origin/master' have diverged.
    
    我该如何解决这个问题

    注意:我没有推;这与推动无关


    注意:简单地再次拉动并不能解决问题;它只是在我已有的基础上重新合并了提交的D,E(尽管D,E在历史上已经存在),这也会产生产生多余冲突的副作用

    下面的一个答案表明,现在的历史是:

    - A - B' - C' - F' - G' - H' (master)
    \
     D - E (origin/master)
    
    这并不完全正确-实际上是:

    - A - B' - C' - D(?) - E(?) - F' - G' - H' (master)
    \
     D - E (origin/master)
    
    因此,我的问题。我希望它是:

    - A - B' - C' - F' - G' - H' (master)
    \         /
     D - E (origin/master)
    

    我猜您没有使用git-rebase的
    -p
    选项,这意味着您所做的拉操作,合并提交D和E,被抹去了。如果这就是所发生的一切,那么很简单:再拉一次。如果发生了这种情况,您的历史将如下所示:

    - A - B' - C' - F' - G' - H' (master)
    \
     D - E (origin/master)
    
        B' - C' - F' - G' - H' (master)
       /
    - A - B - C - X - F - G - H (origin/master)
    \            /
     D - E ------
    
    这是你的分歧

    如果您确实保留了合并,那么很可能这只是因为在此期间新的内容被推送到了原点:

    - A - B' - C' - X' - F' - G' - H' (master)
    \              /
     D - E -------- - Z (origin/master)
    
    因此,解决方案,再一次,将是拉动

    但是,如果您推送了包含原始提交B的内容,那么就不应该重新设置基址。这总是会导致分歧,这不是一种有趣的方式。您的历史记录如下所示:

    - A - B' - C' - F' - G' - H' (master)
    \
     D - E (origin/master)
    
        B' - C' - F' - G' - H' (master)
       /
    - A - B - C - X - F - G - H (origin/master)
    \            /
     D - E ------
    

    git设计的一个基本事实是,提交的SHA1取决于其父级的SHA1,因此取决于整个祖先链。这就是为什么在调整后,我对所有事情都加上了一个“prime”。即使您没有修改C的内容,提交也会被修改。(另一种可能性,即您保留合并并推送,应该可以推断为最后两张图片的组合。)

    注意:我暂时不会接受我自己的答案,因为我真的很好奇其他(更好的)方法

    我摆脱困境的方式很不优雅:

    # stash F, G, H - can't simply reorder them before D, E since they depend a lot on D, E
    for i in {1..3}; do git reset HEAD^; git stash; done
    # wipe out the weird non-merge D and E commits
    git reset --hard HEAD~2
    # pull to merge D, E again
    git pull
    # restore F, G, H
    for i in {1..3}; do git stash pop; git commit -a; done
    

    +1和“不好玩”确实,如第“”段所述,从…简单地再次拉动并不能解决问题;它只是在我已有的基础上重新应用了提交的D,E(尽管D,E已经存在于历史中),这也有产生多余冲突的副作用。你说得对,我没有使用
    -p
    ;我对修复现状感兴趣,因为我没有使用
    -p
    。而且,我从来没有按过。@Yang:“它只是在我已有的基础上重新应用了提交的D,E”这意味着你已经将设置拉到了重基而不是合并?这是高度相关的信息,正如手册所说:“这是一种潜在的危险操作模式……除非您仔细阅读git rebase(1),否则不要使用此选项。”;它们不会重新设置基址。我应该用不同的措辞,因为“它只是将D,E与我已经拥有的东西重新融合。”你在对我的回答的评论中说D和E已经存在于历史中,但这里你暗示它们不是。但在您的另一条评论中,您还暗示您使用了
    pull--rebase
    ,这意味着您在这里的pull实际上并没有合并。我很高兴能为你找到一个更好的答案,而且我相信有一个答案——如果这个办法奏效,听起来你所要做的就是结帐、重新提取、重新设置基址。但我需要确切地知道历史是什么样子才能给出一个好的答案,而且我现在对自己知道的情况不太自信。@Jefromi
    pull--rebase
    没有被使用。D和E在历史中,我用第二行删去了。我认为你所建议的是一个更好的方法来达到我上面所做的,所以请一定要启发我!