The difference between git pull, git fetch and git clone (and git rebase)

Update: So, over a year later and I’ve had some feedback from a colleague (thanks Ben!). Nothing here is drastically wrong, but some clarifications should help!

When I started out with git …

… who am I kidding, I’m still a git n00b. Today, I tweeted about git. I wanted to know what the differene between pull, fetch and clone is. After discovering that, really, 140 characters isn’t enough to answer the questions, I had a play around.

Git Pull

From what I understand, git pull will pull down from a remote whatever you ask (so, whatever trunk you’re asking for) and instantly merge it into the branch you’re in when you make the request. Pull is a high-level request that runs ‘fetch’ then a ‘merge’ by default, or a rebase with ‘–rebase’. You could do without it, it’s just a convenience.

%> git checkout localBranch
%> git pull origin master
%> git branch
master
* localBranch

The above will merge the remote “master” branch into the local “localBranch”.

Git fetch

Fetch is similar to pull, except it won’t do any merging.

 %> git checkout localBranch
 %> git fetch origin remoteBranch
%> git branch
master
* localBranch
remoteBranch
 

So, the fetch will have pulled down the remoteBranch and put it into a local branch called “remoteBranch”. creates a local copy of a remote branch which you shouldn’t manipulate directly; instead create a proper local branch and work on that. ‘git checkout’ has a confusing feature though. If you ‘checkout’ a local copy of a remote branch, it creates a local copy and sets up a merge to it by default.

Git clone

Git clone will clone a repo int a newly created directory. It’s useful for when you’re setting up your local doodah

%> cd newfolder
%> git clone git@github.com:whatever/something.git
%> git branch
 * master
remoteBranch
 

Git clone additionally creates a remote called ‘origin’ for the repo cloned from, sets up a local branch based on the remote’s active branch (generally master), and creates remote-tracking branches for all the branches in the repo

Git rebase

Finally, git rebase is pretty cool. Anything you’ve changed by committing to your current branch but are no in the upstream are saved to a temporary area, so your branch is the same as it was before you started your changes, IE, clean. It then grabs the latest version of the branch from the remote If you do ‘git pull –rebase’, git will pull down the remote changes, rewind your local branch, then replays all your changes over the top of your current branch one by one, until you’re all up to date. Awesome huh?

Finally..

If you get stuck, run ‘git branch -a’ and it will show you exactly what’s going on with your branches. You can see which are remotes and which are local. This is a good headsup before you start to break things! It’s worth remembering that git branches are basically just a pointer, so to be able to work with those commits you need a local branch which points to somewhere from which those commits are reachable.

Thanks to Ben for the extra stuff, clarifications and calling me an idiot when I get git wrong, because I am, as it’s really pretty simple, except for the simple.


									

17 comments

  1. So in fetch what kind of data are we pulling exactly? Is it code? If so, where does it go? The manual seems to hint that we are grabbing some kind of structural information but I don’t really know what.

    1. So, from the git book:

      The command goes out to that remote project and pulls down all the data from that remote project that you don’t have yet.

      and a but further down it says:

      So, git fetch origin fetches any new work that has been pushed to that server since you cloned (or last fetched from) it.

      So, to me, it sounds like it pulls everything down. But it won’t merge, you’ll need to do that manually. When you do a git status you’ll probably see unstaged modifications.

      1. Everything said by Mike was correct except for: “When you do a git status you’ll probably see unstaged modifications.”. You will only see unstaged modifications if you had unstaged modifications before you fetched. Git fetch will not change any unstaged modifications at all. This is what git fetch really does. Lets say you are on your master branch and you’re pulling from the origin remote’s master branch (which is probably what will happen by default if you do a “git fetch”). Your master branch will be unchanged and your staged files will also be unchanged. Your origin/master branch will be updated. The origin/master branch represents that state of the files on the origin’s master branch if you do a git pull it also updates the origin/master branch and then merges origin/master to your master. So with the scenario listed above a git pull is equivelent to a git fetch && git merge origin/master.

  2. Nice day,

    Can I ask something… maybe its not too related to your post but I just want to ask… I am also new to GIT… I am trying to pull, fetch, rebase and clone as well as push… I dont know why, I cant do it because of an error stating “The remote end hung up unexpectedly” :This is the code I wrote: git push file:////172.16.4.42/myrepo repo.git …. Can you help me with it?…. TYSM

  3. Will git pull just pull on the current working branch and not all your remotely tracking branches? For example, I have a dev/homepage and a dev/footer. If I’m in dev/homepage and I git pull will it only pull on that branch or my dev/footer as well?

  4. I’m still having problems wrapping my head around all this. What is the purpose of “checkout” as compared to “clone”, “fetch”, and “pull”? In what cases does one use this?

    1. `checkout` allows you to turn your working directory into a particular revision or branch of a repo. For example, you can do `checkout 82jj282` and it will checkout a particular revision or `checkout my-lovely-branch` and it’ll switch from whatever branch you’re on (probably master) to the my-lovely-branch branch.

      `checkout` is almost entirely local, whereas clone, fetch and pull are working with remote versions of your repo.

      HTH

      1. Mike, thank you, but this is only partly clear. If I understand your explanation correctly, “checkout” puts a copy of a particular branch from the remote repo in your local working directory. But so do clone, fetch, and pull. The differences that I see:
        - clone if you don’t have anything yet in your working directory;
        - pull to update your working directory with the edits from the same branch on the remote repository, and merge with your local edits;
        - fetch will overwrite your working directory with the current revision of the current branch on the remote repo;
        - checkout to overwrite your existing working directory with a particular branch from the remote repository.
        Correct?

  5. What I want usually is not any of these.. What I’m usually wanting to do is a command that will force my local branch to 100% match the remote, downloading anything it needs and deleting anything that doesn’t belong. No “replay” of local changes at all, I want to UNDO them. I’d like to see that as a huge button in the Git Extensions GUI. What I end up doing instead is to completely delete my local tree and then I clone the repository anew. I guess I need to write a script to do the delete/re-clone since it’s not clear anything else produces the same result. Delete/re-clone seems clumsy, like most everything in Git. Yeah, Git is more powerful but what I actually need is ease of use.

    1. Your changes should all be done on a new branch so you’re not breaking master. That way, if things get out of hand, you can delete your branch, switch back to your master branch and create a new branch from the untouched master.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s