50

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 not touch (but which got updated in master) suddenly enter my list of "Changes to be committed".

Why is this? And how do I fix this? I don't want any of these not-by-me changes to get committed.

grautur
  • 29,955
  • 34
  • 93
  • 128
  • 1
    [http://stackoverflow.com/questions/457927/git-workflow-and-rebase-vs-merge-questions](http://stackoverflow.com/questions/457927/git-workflow-and-rebase-vs-merge-questions) - this is what you should look at – Artem Oboturov Apr 12 '12 at 10:10
  • 9
    Rebase and merge offer different workflows. Blindly using rebase instead of merge to "solve" this "problem" is not the right approach. – Noufal Ibrahim Apr 15 '12 at 04:09

7 Answers7

10

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?

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.

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).

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.

There could a git command to tell the git to ignore a bunch of files without using .gitignore. Doing further research into this.

Ivan Lim
  • 179
  • 2
  • 7
  • This is a very interesting strategy, let me try some it up: fish out only the merge conflicts that couldn't be auto merged, merge them manually and then merge again. I assume you do this (a) to have a specific commit with all the changes stuff merged manually and (b) to avoid git blaming you (the merge commit) instead of the actual commit. Sounds like visual studio code is doing something extra on top of what git is doing, do you have a source for that? – Chagai Friedlander Sep 29 '22 at 07:21
8

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.

Yochay
  • 89
  • 1
  • 2
8

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.

Instead of doing:

$ 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.

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.

Conceptually, here is what merge is doing (more here):

Let the current head be called current, and the head to be merged called merge.

  1. Identify the common ancestor of current and merge. Call it ancestor-commit.
  2. 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.
  3. Otherwise, determine the changes between the ancestor-commit and merge.
  4. Attempt to merge those changes into the files in current.
  5. 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.
  6. If there was a conflict, insert appropriate conflict markers and inform the user. No commit is created.
Christopher Perry
  • 38,891
  • 43
  • 145
  • 187
  • 13
    This answer seems off-topic, as one needs to merge several topic-branches, but with changes recently made to master. So one has to merge master into one's own topic branch before carrying on. – Alec May 29 '15 at 08:39
  • 2
    The Q specifically states they used the command `git merge master` from within their branch. Making assumptions about user error is not an answer. Making assumptions about user error that directly contradicts the Q is rude and unhelpful. – Zim Dec 15 '20 at 20:00
  • this is awesome, it saved my day. 100+ votes.. – Paul Pacurar Jun 29 '23 at 20:02
2

Where I find this pop up is if I:

1) create, and work on a branch (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

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

3) go back and make some changes to b1, and then pull b1 into 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)

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.

git merge --abort is your friend, if you're in the middle of a merge full of commits you didn't make.

HammerN'Songs
  • 201
  • 3
  • 13
2

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:

mkdir a
cd a
git init

create a/alpha.docx and save it, then continue with

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

Create a repo b that has a as remote:

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

Modify a/alpha.docx and save it, then continue with

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.

cd ../b
git pull

This will create the file b/beta, and then abort the merge with this error:

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 you know it.
I, personally, would have expected git to remove all the new files when aborting the merge. To quote Noufal Ibrahim's answer above:

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.

lucidbrot
  • 5,378
  • 3
  • 39
  • 68
1

This is pretty natural. Suppose you branched out from master branch into a feature branch. You are commiting changes to the feature branch and after sometime you wish to merge the master branch into the feature branch.

Note that there is a possibility that there were no new changes in the master branch since you had branched out. In such a scenario, a git merge would result in a fast forward merge but we are NOT interested in that. We are assuming that the master branch is having new changes (or extra new files) after we had branched out.

If there are no merge conflicts, a normal git merge would have created a new commit (called the merge commit) containing all those extra new files coming from the master branch automatically in the background.

If there is a merge conflict, the merge operation halts. Git will expect you to resolve the conflicts while keeping the extra new files from the master branch in the staging area. You resolve the conflicts and add the changed files to the staging area and do a git status and you see that there are other files as well. These are the files from the master branch. Now you need to commit all the files in the staging area which will essentially become the merge commit containing the extra new files from the master branch and the files which were having conflicts.

-1

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.

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?

Noufal Ibrahim
  • 71,383
  • 13
  • 135
  • 169
  • 26
    "Why did you merge at all?" question is not an answer to OP's question. – Tomasz Kalkosiński Nov 06 '13 at 14:33
  • 6
    When you do a merge (from a public branch others push to), changes which you've not made yourself do come into your branch. That's what you'd expect from a merge. If you don't want any "not-by-me changes", then you shouldn't merge. That's what seems logical to me anyway. – Noufal Ibrahim Nov 06 '13 at 15:10
  • 2
    "... all files that can be automatically merged ... are automatically merged and staged." What's the point of this? If I don't have any local changes to the files then committing these changes has no effect beyond confusing me (which seems to be git's main purpose). – Jamie Ide Jun 05 '14 at 14:53
  • I'm simply detailing what happens when a merge operation is run. Trees corresponding to two commits need to be merged. This is done by checking the tree and doing what I've mentioned. If my wording confused you, let me know exactly what you don't understand and I might be able to clarify. – Noufal Ibrahim Jun 06 '14 at 03:14
  • 3
    Noufal- since OP didn't touch any of these files, shouldn't git realize that these files were already merged outside of this workflow and utilize that latest commit? – IcedDante Jun 29 '15 at 14:19
  • @IcedDante Even if there is a single file that has a merge conflict (which is the situation as from what I understand), the process of merging gets halted and the user has to intervene. The files which had no conflicts will be there read for commit. The user has to fix the merge conflict, add the conflicted file (to mark it as resolved) and then do the merge. – Noufal Ibrahim Jun 29 '15 at 16:34
  • 1
    @NoufalIbrahim I did the same thing, and I think the op wanted to commit the changes from local to remote origin, which cannot be done unless the local branch is up to date with origin, which requires a pull and merge. Makes sense? – user2441441 Aug 30 '16 at 23:58
  • I think git should auto commit those files which automatically merged succeed and only display the un-succeed files when git status, this should be the desired way and is what @grautur wants – BruceSun Jun 10 '20 at 00:32
  • Git cannot commit "files". It commits multiple files in a single shot. If it does something like what you're suggesting, we'll get more than one commit for a single merge. – Noufal Ibrahim Jun 10 '20 at 04:46
  • @NoufalIbrahim Did not get what the question is "I don't want any of these not-by-me changes to get committed.". I have faced the similar problems related to git – vkrishna17 Aug 27 '21 at 10:06