git Git合并冲突后,很多我没有接触的文件变成了要提交的更改
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9189867/
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
After a Git merge conflict, a lot of files I didn't touch become changes to be committed
提问by grautur
So I'm working in a branch, make some changes, and run git merge master
. I get a merge conflict on one of the files I modified (which I know how to deal with), but for some reason, a bunch of files I did nottouch (but which got updated in master) suddenly enter my list of "Changes to be committed".
所以我在一个分支中工作,进行一些更改,然后运行git merge master
. 我得到我修改过的文件(我知道如何处理)的一个合并冲突,但由于某些原因,一堆文件我根本不碰(但得到了在主更新)突然进入我的“更改列表承诺”。
Why is this? And how do I fix this? I don't want any of these not-by-me changes to get committed.
为什么是这样?我该如何解决这个问题?我不希望任何这些非我的更改被提交。
采纳答案by Noufal Ibrahim
When you attempt a merge, all files that can be automatically merged (e.g. where you don't have any changes in your local branch but which have been modified on the source branch), are automatically merged and staged. Files which could not be automatically merged are updated in your working area with conflict markers and you have to fix them.
当您尝试合并时,所有可以自动合并的文件(例如,在本地分支中没有任何更改但在源分支上已修改的文件)将自动合并和暂存。无法自动合并的文件会在您的工作区域中使用冲突标记进行更新,您必须修复它们。
Git always assembles new commits in the staging area before committing them. The merge does the same thing. A new commit with all the changes from the source branch is created in the staging area. In case of a conflict, this process of updating the staging area is interrupted and control is given to you. That's why this happens. Once you commit, a "merge commit" will get created in the repository that has both the source and target branches as parents.
Git 总是在提交之前在暂存区组装新的提交。合并做同样的事情。在暂存区域中创建一个包含来自源分支的所有更改的新提交。如果发生冲突,此更新暂存区的过程将被中断,并将控制权交给您。这就是为什么会发生这种情况。提交后,将在源分支和目标分支作为父分支的存储库中创建“合并提交”。
As for " I don't want any of these not-by-me changes to get committed.", why did you do a merge at all if you don't want any changes?
至于“我不希望提交任何这些非我所做的更改。”,如果您不想要任何更改,为什么要进行合并?
回答by Yochay
I think the problem with this GIT way of doing things is that after the commit, a "push" will be performed. The "push" will include all committed files - including files that the "pusher" didn't touch. This makes tracking changed very complicated.
我认为这种 GIT 做事方式的问题在于,在提交之后,将执行“推送”。“推送”将包括所有提交的文件——包括“推送者”没有触及的文件。这使得跟踪更改非常复杂。
回答by Christopher Perry
The reason this happened is because you most likely did the opposite of what you were intending to do.
发生这种情况的原因是因为您很可能做了与您打算做的相反的事情。
Let's suppose your working branch is called topic-branch
.
假设您的工作分支名为topic-branch
。
Instead of doing:
而不是做:
$ git merge master
$ git merge master
you could have done:
你本可以这样做:
$ git checkout master
$ git merge topic-branch
In English, instead of merging the master
branch into topic-branch
you could have merged topic-branch
into master
.
在英语中,您可以将master
分支topic-branch
合并topic-branch
到master
.
To understand why this achieves the desired result we can examine the statement made in a previous answer:
要了解为什么这会达到预期的结果,我们可以检查之前答案中的陈述:
When you attempt a merge, all files that can be automatically merged (e.g. where you don't have any changes in your local branch but which have been modified on the source branch), are automatically merged and staged.
当您尝试合并时,所有可以自动合并的文件 (例如,在本地分支中没有任何更改但在源分支上已被修改的文件)将自动合并和暂存。
The problem you are having is simply merge
trying to do its job. The files aren't changed in your topic branch, but they are on the branch you are merging into it. If you look at this in the opposite direction of merging the topic-branch
into master
the problem goes away because it only considers the files you've modified.
您遇到的问题只是merge
试图完成其工作。这些文件不会在您的主题分支中更改,但它们位于您要合并到其中的分支上。如果您从将问题合并topic-branch
到相反的方向看这个master
问题就会消失,因为它只考虑您修改过的文件。
Conceptually, here is what merge is doing (more here):
从概念上讲,这里是 merge 正在做的事情(更多在这里):
Let the current head be called current, and the head to be merged called merge.
- Identify the common ancestor of current and merge. Call it ancestor-commit.
- Deal with the easy cases. If the ancestor-commit equals merge, then do nothing. If ancestor-commit equals current, then do a fast forward merge.
- Otherwise, determine the changes between the ancestor-commit and merge.
- Attempt to merge those changes into the files in current.
- If there were no conflicts, create a new commit, with two parents, current and merge. Set current (and HEAD) to point to this new commit, and update the working files for the project accordingly.
- If there was a conflict, insert appropriate conflict markers and inform the user. No commit is created.
让当前的头部称为current,将要合并的头部称为merge。
- 确定 current 和 merge 的共同祖先。称之为祖先提交。
- 处理简单的情况。如果祖先提交等于合并,则什么都不做。如果祖先提交等于当前,则执行快进合并。
- 否则,确定祖先提交和合并之间的更改。
- 尝试将这些更改合并到当前文件中。
- 如果没有冲突,创建一个新的提交,有两个父项,当前和合并。将当前(和 HEAD)设置为指向这个新提交,并相应地更新项目的工作文件。
- 如果存在冲突,请插入适当的冲突标记并通知用户。没有创建提交。
回答by Ivan Lim
I encountered the same problem myself, and came up with an intermediate solution. Need to find a better one down the road.
我自己也遇到了同样的问题,并想出了一个中间解决方案。需要在路上找到一个更好的。
First to address the question posed by @NoufalIbrahim: As for " I don't want any of these not-by-me changes to get committed.", why did you do a merge at all if you don't want any changes?
首先解决@NoufalIbrahim 提出的问题:至于“我不希望提交任何这些非我的更改。”,如果您不想进行任何更改,为什么要进行合并?
You have misunderstood @grautur intention. The changes are needed, but not as part of a new commit. For example, 1 file was added locally, 100 files came from merge. The new commit should have 1 changed file and not 101 changed file. This is especially important if an automatic merge is not possible, but a pull request is initiated and someone has to review the commit. You want the reviewer to review 1 file, not 101 files.
你误解了@grautur 的意图。需要更改,但不是作为新提交的一部分。比如本地添加了1个文件,合并了100个文件。新提交应该有 1 个更改的文件,而不是 101 个更改的文件。如果无法进行自动合并,但发起了拉取请求并且必须有人提交,则这一点尤其重要。您希望审阅者审阅 1 个文件,而不是 101 个文件。
What I am currently doing is this: let's say we have branch 'master' and 'feature'. 'feature' is created from 'master' and I only make changes to files in 'feature'. When new changes are pulled into 'master', git merge master
inside 'feature' will introduce new files (and these are staged automatically in VSCode, which is the IDE I use).
我目前正在做的是:假设我们有分支“master”和“feature”。“功能”是从“主”创建的,我只对“功能”中的文件进行更改。当新更改被拉入“master”时,git merge master
“feature”内部将引入新文件(这些文件会在 VSCode 中自动暂存,这是我使用的 IDE)。
What I do next is unstage all of these files. Basically ignore them. Only add and commit files that I change. Push 'feature' to origin/remote repo, create pull request. When request is accepted and commit is merged to the main branch, delete 'feature' locally and remotely. Pull changes to 'master' local and create a new branch to work on new feature. This new branch will not have a bunch of unstaged files.
我接下来要做的是取消暂存所有这些文件。基本上无视他们。只添加和提交我更改的文件。将“功能”推送到源/远程存储库,创建拉取请求。当请求被接受并将提交合并到主分支时,在本地和远程删除“功能”。将更改拉到“master”本地并创建一个新分支以处理新功能。这个新分支不会有一堆未暂存的文件。
There could a git command to tell the git to ignore a bunch of files without using .gitignore. Doing further research into this.
可以有一个 git 命令告诉 git 在不使用 .gitignore 的情况下忽略一堆文件。对此进行进一步研究。
回答by HammerN'Songs
Where I find this pop up is if I:
我发现这个弹出的地方是如果我:
1) create, and work on a branch (b1)
1) 创建并在分支上工作 (b1)
---m
\
b1
---m
\
---b1
2) create a new branch (b2) from b1, during which time someone else makes changes to completely unrelated code in master
2) 从 b1 创建一个新分支 (b2),在此期间其他人对 master 中完全不相关的代码进行更改
----------------m
\
---b1
\
b2
3) go back and make some changes to b1, and then pull b1 into master.
3)回去对b1做一些修改,然后把b1拉进master。
----------------m
\ /
-------b1
\
--b2
If I then try to pull from master into b2, I'll get a conflict because of the changes made to b1 after creating b2. If I fix the conflict, the resulting commit will include all changes that have occurred on master since the branch of b1, as if I had performed them. (git blame
seems to be able to tell the original author though)
如果我然后尝试从 master 拉入 b2,我会因为创建 b2 后对 b1 所做的更改而发生冲突。如果我修复了冲突,结果提交将包括自 b1 分支以来在 master 上发生的所有更改,就好像我已经执行了它们一样。(不过git blame
似乎可以告诉原作者)
In this scenario, if I instead first pull from b1 into b2, and sort out the merge there, then I can then pull from master without issue, and the pulled-in irrelevant commits won't show up as changes I've made.
在这种情况下,如果我先从 b1 拉入 b2,然后在那里整理合并,那么我可以毫无问题地从 master 拉出,并且拉入的无关提交不会显示为我所做的更改。
git merge --abort
is your friend, if you're in the middle of a merge full of commits you didn't make.
git merge --abort
是你的朋友,如果你正在合并你没有做的提交。
回答by lucidbrot
A way to reproduce the issue
重现问题的方法
is using a word file to cause the merge failure. Here's how to reproduce the issue:
create a repo a
:
正在使用 word 文件导致合并失败。以下是重现问题的方法:
创建一个 repo a
:
mkdir a
cd a
git init
create a/alpha.docx
and save it, then continue with
创建a/alpha.docx
并保存它,然后继续
git add alpha.docx
git commit -m "initial alpha commit"
Create a repo b
that has a
as remote:
创建一个回购b
具有a
远程:
cd ..
mkdir b
cd b
git clone ../a
Modify a/alpha.docx
and save it, then continue with
修改a/alpha.docx
并保存,然后继续
cd ../a
touch beta # create some file
git commit -am "modified alpha"
Open b/alpha.docx
in word and start typing something. Do not save it. This marks the file as busy.
b/alpha.docx
在 word 中打开并开始输入内容。不要保存它。这将文件标记为繁忙。
cd ../b
git pull
This will create the file b/beta
, and then abort the merge with this error:
这将创建文件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
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
If you now try to pull again, after closing word and discarding your local changes, this happens:
如果您现在尝试再次拉取,在关闭单词并丢弃本地更改后,会发生这种情况:
$ 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
How to deal with this
如何处理这个
Way 1
方式一
git reset --hard HEAD
git clean -f -d
git pull
as suggested here
正如这里所建议的
Way 2
方式二
git add -A
git stash
git pull
git stash drop # optional
Why this is
这是为什么
I don't know. Feel encouraged to edit this section if youknow it.
I, personally, would have expected git to remove all the new files when aborting the merge.
To quote Noufal Ibrahim's answerabove:
我不知道。如果您知道,欢迎您编辑此部分。
我个人希望 git 在中止合并时删除所有新文件。引用上面Noufal Ibrahim 的回答:
A new commit with all the changes from the source branch is created in the staging area. In case of a conflict, this process of updating the staging area is interrupted and control is given to you. That's why this happens.
在暂存区域中创建一个包含来自源分支的所有更改的新提交。如果发生冲突,此更新暂存区的过程将被中断,并将控制权交给您。这就是为什么会发生这种情况。