git: fetch and merge, don’t pull

This is too long and rambling, but to steal a joke from Mark Twain Blaise Pascal I haven’t had time to make it shorter yet.  There is some discussion of this post on the git mailing list, but much of it is tangential to the points I’m trying to make here.

One of the git tips that I find myself frequently passing on to people is:

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.

Branches

Before I explain the advice about git pull any further it’s worth clarifying what a branch is. Branches are often described as being a “line of development”, but I think that’s an unfortunate expression since:

  • If anything, a branch is a “directed acyclic graph of development” rather than a line.
  • It suggests that branches are quite heavyweight objects.

I would suggest that you think of branches in terms of what defines them: they’re a name for a particular commit and all the commits that are ancestors of it, so each branch is completely defined by the SHA1sum of the commit at the tip. This means that manipulating them is a very lightweight operation – you just change that value.

This definition has some perhaps unexpected implications. For example, suppose you have two branches, “stable” and “new-idea”, whose tips are at revisions E and F:

  A-----C----E ("stable")
   \
    B-----D-----F ("new-idea")

So the commits A, C and E are on “stable” and A, B, D and F are on “new-idea”. If you then merge “new-idea” into “stable” with the following commands:

    git checkout stable   # Change to work on the branch "stable"
    git merge new-idea    # Merge in "new-idea"

… then you have the following:

  A-----C----E----G ("stable")
   \             /
    B-----D-----F ("new-idea")

If you carry on committing on “new idea” and on “stable”, you get:

  A-----C----E----G---H ("stable")
   \             /
    B-----D-----F----I ("new-idea")

So now A, B, C, D, E, F, G and H are on “stable”, while A, B, D, F and I are on “new-idea”.

Branches do have some special properties, of course – the most important of these is that if you’re working on a branch and create a new commit, the branch tip will be advanced to that new commit. Hopefully this is what you’d expect. When merging with git merge, you only specify the branch you want to merge into the current one, and only your current branch advances.

Another common situation where this view of branches helps a lot is the following: suppose you’re working on the main branch of a project (called “master”, say) and realise later that what you’ve been doing might have been a bad idea, and you would rather it were on a topic branch. If the commit graph looks like this:

   last version from another repository
      |
      v
  M---N-----O----P---Q ("master")

Then you separate out your work with the following set of commands (where the diagrams show how the state has changed after them):

  git branch dubious-experiment

  M---N-----O----P---Q ("master" and "dubious-experiment")

  git checkout master

  # Be careful with this next command: make sure "git status" is
  # clean, you're definitely on "master" and the
  # "dubious-experiment" branch has the commits you were working
  # on first...

  git reset --hard <SHA1sum of commit N>

       ("master")
  M---N-------------O----P---Q ("dubious-experiment")

  git pull # Or something that updates "master" from
           # somewhere else...

  M--N----R---S ("master")
      \
       O---P---Q ("dubious-experiment")

This is something I seem to end up doing a lot… :)

Types of Branches

The terminology for branches gets pretty confusing, unfortunately, since it has changed over the course of git’s development. I’m going to try to convince you that there are really only two types of branches. These are:

(a) “Local branches”: what you see when you type git branch, e.g. to use an abbreviated example I have here:

       $ git branch
         debian
         server
       * master

(b) “Remote-tracking branches”: what you see when you type git branch -r, e.g.:

       $ git branch -r
       cognac/master
       fruitfly/server
       origin/albert
       origin/ant
       origin/contrib
       origin/cross-compile

The names of tracking branches are made up of the name of a “remote” (e.g. origin, cognac, fruitfly) followed by “/” and then the name of a branch in that remote respository. (“remotes” are just nicknames for other repositories, synonymous with a URL or the path of a local directory – you can set up extra remotes yourself with “git remote”, but “git clone” by default sets up “origin” for you.)

If you’re interested in how these branches are stored locally, look at the files in:

  • .git/refs/heads/ [for local branches]
  • .git/refs/remotes/ [for tracking branches]

Both types of branches are very similar in some respects – they’re all just stored locally as single SHA1 sums representing a commit. (I emphasize “locally” since some people see “origin/master” and assume that in some sense this branch is incomplete without access to the remote server – that isn’t the case.)

Despite this similarity there is one particularly important difference:

  • The safe ways to change remote-tracking branches are with git fetch or as a side-effect of git-push; you can’t work on remote-tracking branches directly. In contrast, you can always switch to local branches and create new commits to move the tip of the branch forward.

So what you mostly do with remote-tracking branches is one of the following:

  • Update them with git fetch
  • Merge from them into your current branch
  • Create new local branches based on them

Creating local branches based on remote-tracking branches

If you want to create a local branch based on a remote-tracking branch (i.e. in order to actually work on it) you can do that with git branch –track or git checkout –track -b, which is similar but it also switches your working tree to the newly created local branch. For example, if you see in git branch -r that there’s a remote-tracking branch called origin/refactored that you want, you would use the command:

    git checkout --track -b refactored origin/refactored

In this example “refactored” is the name of the new branch and “origin/refactored” is the name of existing remote-tracking branch to base it on. (In recent versions of git the “–track” option is actually unnecessary since it’s implied when the final parameter is a remote-tracking branch, as in this example.)

The “–track” option sets up some configuration variables that associate the local branch with the remote-tracking branch. These are useful chiefly for two things:

  • They allow git pull to know what to merge after fetching new remote-tracking branches.
  • If you do git checkout to a local branch which has been set up in this way, it will give you a helpful message such as:
    Your branch and the tracked remote branch 'origin/master'
    have diverged, and respectively have 3 and 384 different
    commit(s) each.

… or:

    Your branch is behind the tracked remote branch
    'origin/master' by 3 commits, and can be fast-forwarded.

The configuration variables that allow this are called “branch.<local-branch-name>.merge” and “branch.<local-branch-name>.remote”, but you probably don’t need to worry about them.

You have probably noticed that after cloning from an established remote repository git branch -r lists many remote-tracking branches, but you only have one local branch. In that case, a variation of the command above is what you need to set up local branches that track those remote-tracking branches.

You might care to note some confusing terminology here: the word “track” in “–track” means tracking of a remote-tracking branch by a local branch, whereas in “remote-tracking branch” it means the tracking of a branch in a remote repository by the remote-tracking branch. Somewhat confusing…

Now, let’s look at an example of how to update from a remote repository, and then how to push changes to a new repository.

Updating from a Remote Repository

So, if I want get changes from the remote repository called “origin” into my local repository I’ll type git fetch origin and you might see some output like this:

  remote: Counting objects: 382, done.
  remote: Compressing objects: 100% (203/203), done.
  remote: Total 278 (delta 177), reused 103 (delta 59)
  Receiving objects: 100% (278/278), 4.89 MiB | 539 KiB/s, done.
  Resolving deltas: 100% (177/177), completed with 40 local objects.
  From ssh://longair@pacific.mpi-cbg.de/srv/git/fiji
     3036acc..9eb5e40  debian-release-20081030 -> origin/debian-release-20081030
   * [new branch]      debian-release-20081112 -> origin/debian-release-20081112
   * [new branch]      debian-release-20081112.1 -> origin/debian-release-20081112.1
     3d619e7..6260626  master     -> origin/master

The most important bits here are the lines like these:

     3036acc..9eb5e40  debian-release-20081030 -> origin/debian-release-20081030
   * [new branch]      debian-release-20081112 -> origin/debian-release-20081112

The first line of these two shows that your remote-tracking branch origin/debian-release-20081030 has been advanced from the commit 3036acc to 9eb5e40. The bit before the arrow is the name of the branch in the remote repository. The second line similarly show that since we last did this, a new remote tracking branch has been created. (git fetch may also fetch new tags if they have appeared in the remote repository.)

The lines before those are git fetch working out exactly which objects it will need to download to our local repository’s pool of objects, so that they will be available locally for anything we want to do with these updated branches and tags.

git fetch doesn’t touch your working tree at all, so gives you a little breathing space to decide what you want to do next. To actually bring the changes from the remote branch into your working tree, you have to do a git merge. So, for instance, if I’m working on “master” (after a git checkout master) then I can merge in the changes that we’ve just got from origin with:

    git merge origin/master

(This might be a fast-forward, if you haven’t created any new commits that aren’t on master in the remote repository, or it might be a more complicated merge.)

If instead you just wanted to see what the differences are between your branch and the remote one, you could do that with:

    git diff master origin/master

This is the nice point about fetching and merging separately: it gives you the chance to examine what you’ve fetched before deciding what to do next. Also, by doing this separately the distinction between when you should use a local branch name and a remote-tracking branch name becomes clear very quickly.

Pushing your changes to a remote repository

How about the other way round? Suppose you’ve made some changes to the branch “experimental” and want to push that to a remote repository called “origin”. This should be as simple as:

    git push origin experimental

You might get an error saying that the remote repository can’t fast-forward the branch, which probably means that someone else has pushed different changes to that branch. So, that case you’ll need to fetch and merge their changes before trying the push again.

Aside

If the branch has a different name in the remote repository (“experiment-by-bob”, say) you’d do this with:

      git push origin experimental:experiment-by-bob

On older versions of git, if “experiment-by-bob” doesn’t already exist, the syntax needs to be:

      git push origin experimental:refs/heads/experiment-by-bob

… to create the remote branch.  However that seems to be no longer the case, at least in git version 1.6.1.2 – see Sitaram’s comment below.

If the branch name is the same locally and remotely then it will be created
automatically without you having to use any special syntax, i.e. you can just do git push origin experimental as normal.

In practice, however, it’s less confusing if you keep the branch names the same. (The <source-name>:<destination-name> syntax there is known as a “refspec”, about which we’ll say no more here.)

An important point here is that this git push doesn’t involve the remote-tracking branch origin/experimental at all – it will only be updated the next time you do git fetch. Correction: as Deskin Miller points out below, your remote-tracking branches will be updated on pushing to the corresponding branches in one of your remotes.

Why not git pull?

Well, git pull is fine most of the time, and particularly if you’re using git in a CVS-like fashion then it’s probably what you want. However, if you want to use git in a more idiomatic way (creating lots of topic branches, rewriting local history whenever you feel like it, and so on) then it helps a lot to get used to doing git fetch and git merge separately.


Posted

in

by

Tags:

Comments

138 responses to “git: fetch and merge, don’t pull”

  1. Yan Avatar
    Yan

    Excellent post! The more example, the more helpful.

  2. dave Avatar
    dave

    It feels like you left out the part where you explained why you should not use git pull. You spent all this time explaining everything, finally landing on git push, and then your closing paragraph explains that git pull is actually ok. So what’s the problem?

    1. mark Avatar

      Well, there’s this earlier paragraph too:

      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.

      The other idea is that if you only ever use “git pull”, it’s possible that you’ll never understand what remote-tracking branches are (or what “origin/master” means in merge commits) and they’re fantasticaly useful.

      But yes, really the main point of the post is to explain about different types of branches, and I feel that the maxim in the title is a nice way of building understanding of that when you’re using git. It also reduces the fear that I’ve seen some git beginners experience when they type “git pull”.

      So, I don’t know. I’m not terribly happy with this post any more, in all honesty, but on the whole people seem to find it useful.

      1. rob Avatar
        rob

        Yes we do [find it useful] :-) Thanks for filling in some of the missing pieces in my git understanding!

      2. Suki Avatar
        Suki

        Concur…my team still finds this very useful as of July 2015. Thanks for writing this lucid post!

      3. Tom Seelbach Avatar
        Tom Seelbach

        Very useful post! For people relatively new to Git, the distinction between pull and fetch/merge is critical to learn. Your post makes it very clear. In fact I think that every 101 “git howto” manual should tell people to use git fetch/merge first, then perhaps use pull as a shortcut later on.

        THANK YOU Mark!

      4. Stephane Avatar
        Stephane

        I’ve quite happy I stumbled on this post, thanks to a link in SO in fact.

      5. Dustin Avatar
        Dustin

        Yes, very useful. I’m a newbie to git (previously an SVN nerd), and this was extremely helpful.

      6. Victor Avatar

        This 2017 and the post remains highly relevant and useful. Bookmarked!

        1. Dov Rine Avatar

          This.

          April 17, 2018

      7. Christian Avatar
        Christian

        Absolutely, still very relevant in 2018. This has absolutely helped me understand much better how git works.

        1. Rikk Avatar
          Rikk

          2020, Still relevant. Thanks!

  3. EyalS Avatar
    EyalS

    Thanks for a really good and clear explanation! funny how millions of users of GIT managed to produce very few good explanations of GIT’s merge/push/pull/fetch commands. This post is a rare gem.

  4. RajendraN Avatar
    RajendraN

    Excellent article !!!

  5. Akinyele Olubodun Avatar

    Nice post. I have always wanted to write something explosive like this on Git. Good job well done.

  6. JohnZ Avatar
    JohnZ

    really great explanation on GIT

  7. Yann Avatar
    Yann

    Thanks dude, very nice post! you helped me to understand some more that just the difference between fetch and pull :)

  8. dennism Avatar
    dennism

    Its a neat, simple easy-to-understand article which explains somewhat tricky concept.
    Hats off dude!!!
    Thanks so much.

    Cheers!!!

  9. Mikhail Avatar
    Mikhail

    I like this article. After reading you can feel neat distinction between “pull” and “fetch, merge” operations.

  10. Arun Avatar
    Arun

    It was indeed a good explanation on difference between Fetch and Pull . Great post and Thanks

  11. John Hampton Avatar
    John Hampton

    Great article. Sometimes it’s good to know a little about what’s going on under the hood.

  12. Mr_and_Mrs_D Avatar

    Nice read!

    Would you consider editing for some newer git ways of doing the same thing as:

    git checkout –track -b refactored origin/refactored

    could just be (note no -b):

    git checkout refactored # this branch does not exist yet but a single remote branch with the same name does

    Git outputs:

    > Branch refactored set up to track remote branch refactored from origin
    >Switched to a new branch ‘refactored’

    and even offers autocomplete in the checkout command (1.9.5 msysgit)

  13. Cookie Avatar
    Cookie

    Thank you, very helpful.

  14. Ryan Betker Avatar

    Hi. Nice post to learn more on git branching, fetching, and merging. Possibly edit here, years later ;)

    In reference to this sentence
    –So now A, B, C, D, E, F, G and H are on “stable”, while A, B, D, F and I are on “new-idea”–

    Am I missing something, or would be that B should be removed from stable category, and category of “new-idea”, A is removed?
    –Update to: now A, C, D, E, F, G and H are on “stable”, while B, D, F and I are on “new-idea”–

  15. Red Avatar
    Red

    Very helpful. Thank you.

  16. David Avatar
    David

    Amazing! Thanks

  17. Bruce Avatar
    Bruce

    Still helping developers after 6+ years. Thanks.

  18. burp Avatar
    burp

    big thanks

  19. vellis Avatar
    vellis

    git pull –rebase

    Your article could be summed up to that. No need for all that BS.

    1. Christopher Pepper Avatar
      Christopher Pepper

      I am disappointed to see so many people saying “dont use git pull” use “git fetch merge”. Especially when personally I don’t like “merge” :p

      Git allows so many different work flows that I think blanket statements like this are unhelpful. Although this blog does go into some good detail.

      In my current project I prefer a branched approach where I work on everything in a branch. I use “pull” to update master and I use git rebase master to “merge” my branch. It works a lot better for merge conflicts in my current context. However I have used different workflows for different projects. some that use “merge” some that use “rebase”. We rarely have the discussion “pull” or “fetch” because I either want to do a “fetch merge” or a “fetch rebase” which I can use git pull –rebase for.

      If stuff goes wrong there is always reflog to revert, diff and git-diffall to work out whats going on.

      1. admin Avatar
        admin

        Hi Christopher – as I’ve said elsewhere in these comments, I think, the title of this post here is intended to be a bit provocative; the real intent of the post is to help people who’ve used git a bit to understand more about remote-tracking branches like “origin/master”.

        It sounds as if your workflows are great for you – you’re using a mixture of `git pull` and `git pull –rebase` (i.e. the equivalents of “‘git fetch’ then ‘git merge’” and “‘git fetch’ then ‘git rebase’”)

        Anyway, the point is much more the substance of the post than the title, but the title still does represent an approach to using git that I find helpful myself.

        1. Christopher Pepper Avatar
          Christopher Pepper

          That’s fair enough. I’m sorry I didn’t actually say it, I actually thought the article itself was very good, but i came across your article after a long line of git pull bashing and needed to vent a bit.

          I get the idea of making the title provocative but I must say its does you a disfavor in some ways. You do cover tracking remote tracking in excellent, clear detail and why it can be useful. Which to me is totally separate to the issue of git fetch vs git pull.

          I might be wrong, but i always felt that git fetch was more to help disjointed / badly connected developers who needed to update their local copy of origin disparately.

          All the remote tracking stuff you go into can be done for either, and again unless your network connection makes git diff etc impractical, I personally don’t get the breathing space argument.

          Anyway, i was trying to apologize for being a bit trolly, (and failed a bit, sorry again), the article is great and I think its a shame that the side point about git fetch distracts from the excellent remote tracking content.

    2. admin Avatar
      admin

      vellis: Some people have found the “BS” in the post helpful as a way of understanding more about git branches; clearly it wasn’t that for you. Using “git pull –rebase” all the time is fine with some workflows, but there are richer ways to use git, and this post might be useful background for them. Anyway, sorry that you apparently felt it wasted your time.

      1. Victor Avatar

        .gitignore

        The post was great and helped us learners a lot.

    3. rayd Avatar
      rayd

      well said

  20. Chathuranga Avatar
    Chathuranga

    One of the best GIT articles ever seen

  21. Nils Avatar
    Nils

    Thanks for the clarification and the write-up!

  22. Anamaria Caez Avatar

    Recruitment Bangkok

  23. Mohammad Samiul Islam Avatar

    This helped me pulling a branch from github. Thanks a lot :)

  24. Stuart MacDonald Avatar
    Stuart MacDonald

    Here’s a question I have not been able to answer anywhere else:

    I have a remote ‘origin’. It has branches ‘master’, ‘Feature_A’, ‘Feature_B’.
    My local has ‘master’, ‘Feature_A’, ‘Feature_B’, ‘experiment_C’. I have ‘experiment_C’ checked out.

    I want to accomplish:
    – getting all the new stuff from origin
    – moving all my local branches up to the new heads
    – while having ‘experiment_C’ checked out

    Essentially, a git pull, but for branches that aren’t checked out.

    This doesn’t appear to be possible, but I can’t find confirm/deny anywhere.

    What I have taken to doing is a shell script that checks out each branch in turn, then does a git pull, then checks out the original branch again, but man is that heavy (there’s a lot of branches in the real scenario).

    Yes, this won’t work in the situation where there are merge conflicts that need to be resolved, BUT, that’s not the case here. In general, all the remote branches are for ‘reading’ only; they will always just be ‘fast-forward’ merges.

  25. Blud Avatar
    Blud

    Good topic ! Thanks

  26. Stephane Avatar
    Stephane

    From that cool article of yours, I got the following…

    I go to my local branch:
    git checkout develop

    I fetch the remote repository:
    git fetch origin
    The local “remote-tracking” branches are then updated or created, the develop branch being one of them.

    I see the difference between the local branch and its local “remote-tracking” branch:
    git diff develop origin/develop

    I merge the local “remote-tracking” develop branch into the local develop branch:
    git merge origin/develop

    Your article beautifully showed me the two steps process of first fetching the “remote-tracking” branch and then mergin it into the local branch. And this was for “pulling from” the server.

    Now, I may have missed a thing here, but I could not see such a two steps process for the “pushing to” the server.

    I could only see a push command like in my case:
    git push develop origin/develop

    I guess there is little, if not no sense, in going for a two steps process when “pushing to” the server, first by merging the local branch into the local “remote-tracking” branch and then by pushing it to the remote server ?

  27. Josh Schneider Avatar
    Josh Schneider

    Hey, Mark, thanks for this nice post. I’m a little confused by a statement in the middle (granted, I’m far from a git expert). Maybe it’s just the phrasing, but I’m not sure:

    “So what you mostly do with remote-tracking branches is one of the following:
    -Update them with git fetch
    -Merge from them into your current branch
    -Create new local branches based on them”

    Are you saying a remote is somehow affected when you issue a git fetch? Now that I’m typing this, I’m thinking you mean “update your local record of the latest remote changes/additions” (without actually changing anything in your working tree, as you say).

    My understanding is that a fetch basically updates your local “snapshot” of the state of your remotes, and nothing else. Is this what you mean, or does a “fetch” actually have some impact on a remote?

    Thanks again

    1. admin Avatar
      admin

      Hi Josh, and I’m glad you liked the post. No, a fetch shouldn’t have any effect on the remote – the section you’re quoting is about “remote-tracking branches” (origin/master, for example), not remotes.

      > Now that I’m typing this, I’m thinking you mean “update your local record of the latest remote changes/additions” (without actually changing anything in your working tree, as you say).

      That’s basically, right – the “local record of the latest remote changes/additions” is remote-tracking branches. Does that make sense?

      1. Josh Avatar
        Josh

        OK, yeah, I wasn’t reading it correctly. You’re talking about a local branch that you’ve set up to track its remote counterpart. Sorry for the confusion.

  28. Pritis Nayak Avatar
    Pritis Nayak

    Thank you.
    It was very helpful in understanding git, and not just fetch vs pull

  29. eduard-andrei haris Avatar
    eduard-andrei haris

    very helpful, thanks

  30. en marbella Maquillaje Permanente cejas Avatar

    Hi, the whole thing is going well here and ofcourse every one is sharing facts, that’s truly
    excellent, keep up writing.

  31. Fabian Pernia Avatar
    Fabian Pernia

    Very clear post. Thanks, I was looking for resources in order to understand the difference between “git pull” and “git fetch” and after reading this post, I got it, and I didn’t have a clear perspective about the references related to “remote branches” (here, the special approach here for me was to take them as a reference to compare changes when make “git fetch” and then base on our needs merge our current work with the remote ones).

  32. Ferguzon Avatar
    Ferguzon

    Thanks for the article. As a recommendation for other posts, try to get to the point of the title of your article. Your title is “git: fetch and merge, not pull” but you spend 85% of the time talking about branches, which is not the reason one is reading the article.

    It’s ok, but it would have been better to just point the problem, analyze it and give your recommendations, rather than spending a lot of text talking about branches (which, finally doesn’t seems to be the goal of the article).

  33. geeky Heather Avatar

    Thanks for an excellent article. git has the worst (most ambiguous) command naming in my recent memory, and the Eclipse plugin does a great job of hiding things you’d want to do “all the time”, like doing that diff between the fetch and merge.

  34. Utkarsh Bhatt Avatar

    Came here from a StackOverflow link and I’m glad. Excellent article.

  35. Lan Olano Avatar

    Very good, thanks.

  36. Rob Fulwell Avatar
    Rob Fulwell

    Great post! Thanks.

  37. Rox Avatar
    Rox

    If we have two branches: master and stage.
    what is rule:
    1) git checkout stage
    git pull origin stage
    git merge master
    git push origin stage
    OR
    2) git checkout stage
    git merge master
    git pull origin stage
    git push origin stage

    Is this important order of git merge and git pull in stage branch?

  38. James Saxon Avatar

    Handy rambling! Thanks.

    BUT.

    I was looking for what happens “next”!

    You wrote: “examine what you’ve fetched before deciding what to do next.”

    With `git diff` that’s about examining. And `merge` is about merging.

    What about interactive merging? How can I use Meld or BeyondCompare (awesome tool) to do a merge where I’m also editing the work?

    I’m asking because documentation unlike code can be very subjective. Sometimes documentation is almost perfect but just not quite. Having a chance to interactively merge for minor tweaks and edits without a “review request” would be really handy.

    It would be nice if this article addressed that “what to do between fetch and merge to make changes.”

    Thanks much!

  39. MikeK Avatar
    MikeK

    Thanks for the article, I found it helpful.
    W.R.T. this line:
    (git fetch may also fetch new tags if they have appeared in the remote repository.)

    Is there a difference between the way “git pull” and “git fetch; git merge” handle tags?
    It seems that “git pull” will not update tags, whereas “git fetch” does update tags.
    In the quote above, why does it say “git fetch may also fetch new tags” rather than will? When does it, and when doesn’t it fetch new tags?

  40. Rahul S Avatar

    Thanks for this article, Mark. Quite useful for folks learning git like myself.

  41. Philippe Carphin Avatar
    Philippe Carphin

    I’ve been saying this to students and calling it “Philippe Carphin’s rule” because I have a whole bit on how I present it.

    Me: “Have you ever heard the rule of Philippe Carphin (they know that’s my own name)?”

    Student : “No”

    Me: “The rule is ‘Never pull’”

    Student : *Looks at me with puzzled eyes*

    Me : *Proceeds to explain the various considerations that your article shows*

    Also, I just discussed this with my boss, he asked for some advice on doing a tricky git procedure. I helped him solve that and showed him the rule, he liked it.

  42. Jim "JR" Avatar

    Cheers! from a Git noob who’s still learning his ropes.

    It’s 2019 pushing 2020 and the article still make sense. OK, maybe not totally, but as someone said before, everybody’s workflow is different.

    Bottom line is that (IMHO) this article should be required reading for *anyone* who wants to do *anything* with Git!

    Thanks again for an excellent article.

  43. Antoine W Avatar
    Antoine W

    Thanks to you git branches and tracking has become crystal clear though I am using git for year!
    Thank you, it is still accurate 10 years after publication.

  44. Jay Darji Avatar
    Jay Darji

    I’ve one git repo in which my team has worked on same file as I’ve worked. When I follow these commands

    git status
    on branch feature-dashboard

    git fetch origin develop
    git merge origin/develop

    git add .
    git commit -m “commited”
    git merge origin/develop

    git push origin feature-dashboard

    The problem is, sometimes when git automerge our code by itself by recursive strategy then mine or others code will wiped out automatically.

    Is I’m doing it wrong? Help me to understood.

  45. Rick Avatar
    Rick

    Hi Mark,
    This is my first day researching GIT and the workflow process. I am accustomed to using TFS and Azure DEVOps; to me all of the needed pieces with GIT is tedious and overwhelming in comparison.

    This article was helpful in describing the fetch/merge process. However, I still did not understand why executing a “pull” command was less desirable until I read other articles stating that a “pull” command is composed of the “fetch” and “merge” commands.

    Knowing that piece of information, along with the points you made, helped me understand the advantage of using the two step process. Including the information about the composition of the “pull” command in the beginning of your article would be very helpful for beginners.

    Thanks for sharing!

  46. Gaurav Singh Avatar
    Gaurav Singh

    good explanation, helps a lot.

  47. Peter Henry Avatar
    Peter Henry

    I just had to leave a comment on this article. This is an AMAZING write up that has finally brought clarity to me on how branches & Git in general works.

    It explained all of the main patterns/combinations that branches its related features show up in which really served to illuminate how the system actually works. I can’t see any way that this article could be shorted without taking away from this.

    Saw this link in a Stack Overflow comment & I’m glad that I clicked it!

    Thank you very much Mark!

    1. mark Avatar

      Thanks for such very kind comments, Peter. It’s really nice to know that people are still finding this helpful!

  48. Tel Avatar
    Tel

    It’s 2023 and it’s still a great blog. Well done Mark
    This blog is great for those starting in GIT. Bookmarked and shared with my team, and linked in our documentation as a must-read.

Leave a Reply to Chathuranga Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.