How will Git merge this?

John and Tom clone the same remote repo.
The content of remote repo is like this:


John make a local commit like this, ie, it moves the FileA.c into a folder named John and commit it locally.

  • git diff - external viewer - get all diff results
  • difference between `git checkout HEAD — fileA.cpp` vs `git checkout — fileA.cpp`
  • How to convert files in github repo to a gist
  • Created an unwanted branch in git, want to get rid of it
  • git sandbox for anyone to pull/push to?
  • Ignore future modifications of a .gitignore'd file which was added with git add -f
  • John\FileA.c

    Tom also make a local commit like this, ie, it moves the FileA.c into a folder named Tom and commit it locally.


    If Tom and John both push their local repos to the remote repo, say GitHub, how will Git merge this?

    I hope I made myself clear.

  • Compare two git repositories including all branches
  • How to split angular app client / server side code in git repositories
  • Unable to install Git-core+svn by MacPorts
  • Git returning null on hudson
  • Gitlab web interface - download snapshot size is ZERO
  • gitpython and git diff
  • 6 Solutions collect form web for “How will Git merge this?”

    When you do git commit but don’t do git push, the changes are added in your local repository and are not committed to the global repo. So, whosoever pushes his changes first, he won’t get any conflicts since the remote server doesn’t know about the changes made by other user that are not yet pushed. Later when the next user tries to push the changes, git will give error that the global repo has been changed and you must pull the changes first. Since, the changes are in the same file and the location has been changed, There will be a conflict, which would not be resolved by git itself.
    The next user will have to make the changes again and push it so as to update the global repo.

    Git/SVN/etc, do a merge as best as possible: if they see that separate, non interfering lines of code have been added/deleted/modified, then it will simply combine those changes made by John/FileA.c and Karen/FileA.c (its become practice to make someone in your example a girl =P). If the merge script see’s that the same lines of code have been edited then it will mark it as conflict in the file.

    I think this point has been made, but this process occurs locally; either by Karen or John, depending on who was the person to try and push last. The person who pushed last will be notified to pull from the remote repo and resolve any conflicts before pushing their own changes.

    Git will never merge during push. One of the two devs (the poor one who tries to push last) has to resolve the conflict locally and tell git where to move the file. Git cannot know where the file should end up without human intervention.

    # dev1
    git clone …
    mkdir John && git mv FileA.c John/FileA.c
    git commit -m 'move file to john subdir'
    git push origin master
    # dev2
    git clone …
    mkdir Tom && git mv FileA.c Tom/FileA.c
    git commit -m 'move file to tom subdir'
    git push origin master
    # git errors out: non-fast-forward, pull first to resolve potential conflicts
    git pull origin master
    # merge conflict in FileA.c
    # tell git which file to delete and which file to keep:
    git rm Tom/FileA.c && git add John.FileA.c
    git commit # creates a merge commit
    git push origin master

    A second push operation will fail; merge has to be done locally. In this case there will be a conflict that must be resolved manually.

    The nice thing about git is that it’s easy to try these things out for yourself without affecting any servers. The result for the last guy to push is:

    02:32:54 ~/desktop/tom
    $ git push
    To /cygdrive/h/desktop/test
     ! [rejected]        master -> master (non-fast-forward)
    error: failed to push some refs to '/cygdrive/h/desktop/test'
    To prevent you from losing history, non-fast-forward updates were rejected
    Merge the remote changes (e.g. 'git pull') before pushing again.  See the
    'Note about fast-forwards' section of 'git push --help' for details.
    02:32:54 ~/desktop/tom
    $ git pull
    remote: Counting objects: 3, done.
    remote: Total 2 (delta 0), reused 0 (delta 0)
    Unpacking objects:  50% (1/2)   Unpacking objects: 100% (2/2)   Unpacking objects: 100% (2/2), done.
    From /cygdrive/h/desktop/test
       307f68a..2539f44  master     -> origin/master
    error: refusing to lose untracked file at 'John/FileA.c'
    error: refusing to lose untracked file at 'John/FileA.c'
    CONFLICT (rename/rename): Rename "FileA.c"->"Tom/FileA.c" in branch "HEAD" rename "FileA.c"->"John/FileA.c" in "2539f448bb15d10f14bef74688dc3470975c2dbf"
    CONFLICT (rename/rename): Rename "FileA.c"->"Tom/FileA.c" in branch "HEAD" rename "FileA.c"->"John/FileA.c" in "2539f448bb15d10f14bef74688dc3470975c2dbf"
    Automatic merge failed; fix conflicts and then commit the result

    Git is nice and asks which rename is the correct one. Note that not all version control systems are capable of detecting this kind of rename/rename conflict.

    The key point from the other answers is that git doesn’t guess what should happen [using some pre-coded presumption], rather it will warn the user of the difficulty because it can’t mind read the various user intentions.

    Most other systems which claim the ability to do such merges fail the clairvoyance test – they don’t know what you really wanted. Let the intelligent folk (that’s you and me 😉 make the decisions.

    Git Baby is a git and github fan, let's start git clone.