git pull VS git fetch, git merge experiments: better do git diff first

Overview

This is to keep results with explanation from my experiments testing on git pull, get fetch, git diff, git merge (conflict) in a setting of working with remote repositories.

Experiment work flow

1) In the first place, I want to do “git pull” to synchronize the contents from the remote branch. However, I found the unsatisfactory part is that “git pull” will update the local git repository, update the git log history, update all the local files with the latest version without allowing me to check/diff the changes. More on this below.

2) Then I remember “git fetch” and want to check the difference between them “git pull” VS “git fetch”, so the following are some resources I found which make sense to me:

  • “git pull” is shorthand for “git fetch” followed by “git merge FETCH_HEAD”.
  • Merge into the current branch the remote branch next:  $ git pull origin next

At the current point, to my knowledge, I thought different from TFS, there is no auto diff when the “git merge” is performed, then I raise the question: how does git handle some “git merge conflict” which cannot be automatically resolved??? I found myself a bit wrong by carrying out the following experiment flow: So the most common type of conflict (Edit Conflict) happens when two branches have changed the same part of the same file, and then those branches are merged together. This is the first mistake I make, in 1) the unsatisfactory part I stated is not completely on the git side. By reading the definition again, I understand git in another way that I assume the git will merge the changes into my local copy anyways (even I changed a line in its middle part, e.g., change “ABCD” into “ACBD”), git won’t prompts that there is such edit conflict because my local copy is not changed, when i do “git pull”, to git, it interpret it as I want those remote changes, I have been clear about that and want to pull those changes into my local copy. In a different case I modified the local file and commit a change in local repository, then both the local and remote branch has changes, in this case, git will be more careful and let me to handle those conflicts by inserting some symbols into the conflicted file.

The concrete results are as follows:

a) The remote repository has a new change committed. I do “git fetch” then. Interestingly, “git fetch” won’t change our working copy (I checked that and found git log does not change, local copy does not change, then what changes?). After “git fetch”, I do “git status”, it just shows:

# On branch master
# Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
#
nothing to commit (working directory clean)

To me, this means that “git fetch” may only update some meta data (especially about the remote branch) while leave all the other local contents untouched.

b) OK, then I modified a local file and then check into local branch, then I do “git pull”, it shows:

Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.

When this sort of conflict occurs, git writes a special block into the file that contains the contents of both versions where the conflict occurred. To complete this type of merge, use text editor to resolve the conflict, then add the file and commit it to complete the merge.

c) I run “git status”, it shows

# On branch master
 # Your branch and 'origin/master' have diverged,
 # and have 1 and 1 different commit each, respectively.
 #
 # Unmerged paths:
 # (use "git add/rm ..." as appropriate to mark resolution)
 #
 # both modified: test.txt
 # no changes added to commit (use "git add" and/or "git commit -a")

Note that, only after “git pull” you will find the above prompts, if you just commit locally, then git status will only prompts you that the local working directly is clean (since you committed), and your local repository is 1 commit ahead of the remote one (because your local meta data has not been updated, in your local meta data, the remote branch is still the old one), you will see the following instead:

# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit (working directory clean)

d) Then I edit the test.txt and commit the changes: git commit -m “resolve merge edit conflict”. Different from normal commit, you will see the following prompts instead:

[master xxxxxx] resolve merge edit conflict

So this commit is actually aware of that you are actually resolving the merge conflict on the file. Git is smart!!!

e) if your remote branch is not changed since your last pull, and you committed into your local repository several times, and if you run “git pull”, you probably will see

git pull Already up-to-date.

This means, the order matters, the fact that whether your local copy is more recent or not matters. And if you run git status, you will probably see something like the following:

# On branch master
# Your branch is ahead of 'origin/master' by 3 commits.
#
nothing to commit (working directory clean)

Practical Suggestions

I found that some good resource and I list them as follows

(A) The first is how to do diff before git pull from stackoverflow:

1) Add any remote repositories you want to compare: 
git remote add foobar git://github.com/user/foobar.git 

2) Update your local copy of a remote:
git fetch foobar

Fetch won't change your working copy. Some concepts in git to my own understanding: "working copy" refers to the actual files you working on locally; "index" refers to a single file to keep track of which files or changes which should be included into the next commit; "Repository" refers to (.git) folder. 

3) Compare any branch from your local repository to any remote you've added:
git diff master foobar/master

(B) I quite agree the following opinion from http://longair.net/blog/2009/04/16/git-fetch-and-merge/

Don’t use git pull, use git fetch and then git merge.

The problem with git pull is that it has all kinds of helpful magic that means you don’t really have to learn about the different types of branch in git. Mostly things Just Work, but when they don’t it’s often difficult to work out why. What seem like obvious bits of syntax for git pull may have rather surprising results, as even a cursory look through the manual page should convince you. The other problem is that by both fetching and merging in one command, your working directory is updated without giving you a chance to examine the changes you’ve just brought into your repository. Of course, unless you turn off all the safety checks, the effects of a git pull on your working directory are never going to be catastrophic, but you might prefer to do things more slowly so you don’t have to backtrack.

(C) This is also a good one to lean how to working with git between remote and local branches: http://marlacorinne.4parkers.com/2012/07/20/git-pull-vs-git-fetch-then-merge/

Summary

This is to keep results with explanation from my experiments testing on git pull, get fetch, git diff, git merge (conflict) in a setting of working with remote repositories.

#

Written on November 7, 2014