【问题标题】:After a Git merge conflict, a lot of files I didn't touch become changes to be committed在 Git 合并冲突之后,很多我没有接触到的文件变成了要提交的更改
【发布时间】:2018-11-16 15:15:50
【问题描述】:

所以我在一个分支中工作,进行一些更改,然后运行git merge master。我在我修改的一个文件上遇到了合并冲突(我知道如何处理),但由于某种原因,我没有接触过一堆文件(但在 master 中更新了)突然进入我的“要提交的更改”列表。

这是为什么?我该如何解决这个问题?我不希望任何这些不是我自己的更改被提交。

【问题讨论】:

标签: git merge


【解决方案1】:

我自己也遇到了同样的问题,并想出了一个中间解决方案。需要在未来找到更好的。

首先要解决@NoufalIbrahim 提出的问题:至于“我不希望提交任何这些不是我的更改。”,如果您不想要,为什么要进行合并有什么变化吗?

您误解了@grautur 的意图。需要进行更改,但不作为新提交的一部分。例如,本地添加了 1 个文件,100 个文件来自合并。新提交应该有 1 个更改的文件,而不是 101 个更改的文件。如果无法进行自动合并,这一点尤其重要,但发起了拉取请求并且必须有人审查提交。您希望审阅者审阅 1 个文件,而不是 101 个文件。

我目前正在做的是:假设我们有分支'master'和'feature'。 “功能”是从“主”创建的,我只对“功能”中的文件进行更改。当新的更改被拉入“master”时,“feature”中的git merge master 将引入新文件(这些文件会在我使用的 IDE VSCode 中自动暂存)。

我接下来要做的是取消暂存所有这些文件。基本上无视他们。仅添加和提交我更改的文件。将“功能”推送到源/远程仓库,创建拉取请求。当请求被接受并将提交合并到主分支时,在本地和远程删除“功能”。将更改拉到“主”本地并创建一个新分支以处理新功能。这个新分支不会有一堆未暂存的文件。

可以有一个 git 命令告诉 git 在不使用 .gitignore 的情况下忽略一堆文件。对此进行进一步研究。

【讨论】:

    【解决方案2】:

    我认为这种 GIT 做事方式的问题在于,在提交之后,将执行“推送”。 “推送”将包括所有已提交的文件——包括“推送者”未触及的文件。这使得跟踪更改变得非常复杂。

    【讨论】:

      【解决方案3】:

      发生这种情况的原因是因为您很可能做了与您打算做的相反的事情。

      假设您的工作分支名为topic-branch

      而不是做:

      $ git merge master

      你本来可以做到的:

      $ git checkout master
      $ git merge topic-branch
      

      在英语中,您可以将topic-branch 合并到master,而不是将master 分支合并到topic-branch

      要了解为什么这会达到预期的结果,我们可以检查上一个答案中的陈述:

      当您尝试合并时,所有可以自动合并的文件 (例如,您在本地分支中没有任何更改,但是 已在源分支上修改),自动合并和暂存。

      您遇到的问题只是merge 试图完成它的工作。这些文件在您的主题分支中没有更改,但它们位于您要合并到其中的分支上。如果您从将topic-branch 合并到master 的相反方向看这个问题,因为它只考虑您修改过的文件。

      从概念上讲,这是合并正在做的事情(更多 here):

      设当前head为current,待合并head 称为合并。

      1. 识别当前和合并的共同祖先。叫它 祖先承诺。
      2. 处理简单的案例。如果祖先提交 等于合并,然后什么也不做。如果祖先提交等于当前, 然后做一个fast forward merge
      3. 否则,确定祖先提交和合并之间的变化。
      4. 尝试将这些更改合并到当前文件中。
      5. 如果没有冲突,创建一个新的提交,有两个父级,当前和合并。放 current(和 HEAD)指向这个新的提交,并更新 相应的项目的工作文件。
      6. 如果存在冲突,请插入适当的冲突标记并通知用户。没有提交 已创建。

      【讨论】:

      • 这个答案似乎离题了,因为需要合并几个主题分支,但最近对 master 进行了更改。所以在继续之前必须将master合并到自己的主题分支中。
      • Q 特别指出他们在他们的分支中使用了命令git merge master。对用户错误做出假设不是答案。对与 Q 直接矛盾的用户错误做出假设是粗鲁且无益的。
      【解决方案4】:

      重现问题的方法

      正在使用 word 文件导致合并失败。以下是重现该问题的方法:
      创建一个仓库a:

      mkdir a
      cd a
      git init
      

      创建a/alpha.docx并保存,然后继续

      git add alpha.docx
      git commit -m "initial alpha commit"
      

      创建一个以 a 为远程的 repo b

      cd ..
      mkdir b
      cd b
      git clone ../a
      

      修改a/alpha.docx并保存,然后继续

      cd ../a
      touch beta                        # create some file
      git commit -am "modified alpha"
      

      在 word 中打开 b/alpha.docx 并开始输入内容。不要保存它。这会将文件标记为忙碌。

      cd ../b
      git pull
      

      这将创建文件b/beta,然后中止合并并出现此错误:

      remote: Counting objects: 3, done.
      remote: Compressing objects: 100% (3/3), done.
      remote: Total 3 (delta 1), reused 0 (delta 0)
      Unpacking objects: 100% (3/3), done.
      From /cygdrive/c/tmp2/b/../a
         a797c43..5c6796e  master     -> origin/master
      Updating a797c43..5c6796e
      error: unable to unlink old 'alpha.docx': Device or resource busy
      

      如果您现在在关闭 word 并丢弃本地更改后再次尝试拉取,则会发生这种情况:

      $ git pull
      Updating a797c43..5c6796e
      error: The following untracked working tree files would be overwritten by merge:
              beta
      Please move or remove them before you merge.
      Aborting
      

      如何处理

      方式 1

      git reset --hard HEAD
      git clean -f -d
      git pull
      

      如建议here

      方式 2

      git add -A
      git stash
      git pull
      git stash drop  # optional
      

      为什么会这样

      我不知道。如果知道,我们鼓励您编辑此部分。
      我个人希望 git 在中止合并时删除所有新文件。 引用以上Noufal Ibrahim's answer

      在源分支中创建一个包含所有更改的新提交 暂存区。在发生冲突的情况下,此更新过程 暂存区被打断,控制权交给你。这就是为什么 发生这种情况。

      【讨论】:

        【解决方案5】:

        我发现这个弹出窗口的地方是如果我:

        1) 创建并处理分支 (b1)

        ---m
            \
             b1
        
        ---m
            \
              ---b1
        

        2) 从 b1 创建一个新分支 (b2),在此期间其他人对 master 中完全不相关的代码进行更改

        ----------------m
            \
              ---b1
                  \
                   b2
        

        3) 回去对b1做一些修改,然后把b1拉进master。

        ----------------m
            \          /
              -------b1
                  \
                    --b2
        

        如果我尝试从 master 拉入 b2,我会因为在创建 b2 后对 b1 所做的更改而发生冲突。如果我修复了冲突,则生成的提交将包括自 b1 分支以来在 master 上发生的所有更改,就好像我已经执行了它们一样。 (git blame 不过好像能告诉原作者)

        在这种情况下,如果我首先从 b1 拉入 b2,并在那里整理合并,然后我可以毫无问题地从 master 拉出,并且拉入的无关提交不会显示为更改已经做好了。

        git merge --abort 是你的朋友,如果你正处于一个充满了你没有做出的提交的合并中。

        【讨论】:

        • 这里也有同样的情况。我刚刚重新定位,它似乎已经解决了问题
        【解决方案6】:

        当您尝试合并时,所有可以自动合并的文件(例如,您在本地分支中没有任何更改但在源分支上已修改的文件)将自动合并和暂存。无法自动合并的文件会在您的工作区域中使用冲突标记进行更新,您必须修复它们。

        Git 总是在提交之前在暂存区组装新的提交。合并做同样的事情。在暂存区域中创建包含来自源分支的所有更改的新提交。如果发生冲突,更新暂存区域的过程将被中断,并由您控制。这就是为什么会发生这种情况。提交后,将在将源分支和目标分支都作为父分支的存储库中创建“合并提交”。

        至于“我不希望任何这些不是我自己的更改被提交。”,如果你不想要任何更改,你为什么要进行合并?

        【讨论】:

        • “你为什么要合并?” question 不是 OP 问题的答案。
        • 当您进行合并(从其他人推送到的公共分支)时,您自己没有进行的更改会进入您的分支。这就是您对合并的期望。如果您不想要任何“非我更改”,那么您不应该合并。无论如何,这对我来说似乎是合乎逻辑的。
        • "...所有可以自动合并的文件...自动合并和暂存。"这有什么意义?如果我没有对文件进行任何本地更改,那么提交这些更改只会让我感到困惑(这似乎是 git 的主要目的)。
        • Noufal- 因为 OP 没有触及这些文件中的任何一个,git 不应该意识到这些文件已经在这个工作流程之外合并并利用最新的提交吗?
        • @NoufalIbrahim 我做了同样的事情,我认为操作想要提交从本地到远程源的更改,除非本地分支与原点保持同步,否则无法完成,这需要拉和合并。有意义吗?
        猜你喜欢
        • 1970-01-01
        • 2021-04-10
        • 1970-01-01
        • 2020-07-25
        • 1970-01-01
        • 2019-04-11
        • 1970-01-01
        • 2014-08-04
        • 2015-04-07
        相关资源
        最近更新 更多