What's the difference between 'git pull' and 'git fetch'?
stackoverflow.com
What's the difference between 'git pull' and 'git fetch'?
1–10 of 29 posts
Re: What's the difference between 'git pull' and 'git fetch'?
#2Now a git pull -r, that's interesting. Does this just fetch the commits and then do a rebase instead of a merge?
Re: What's the difference between 'git pull' and 'git fetch'?
#3`git pull` = `git fetch` + `git merge`
`git fetch` much more often used by those who use the rebase workflow (vs. the merge workflow).
Re: What's the difference between 'git pull' and 'git fetch'?
#4Re: What's the difference between 'git pull' and 'git fetch'?
#5My understanding if git fetch is that the remote. Hangers are stored out if the way, ready to be merged to a branch. git pull is just a convinence function. Now a git pull -r, that's interesting. Does this just fetch the commits and then do a rebase instead of a merge?
Re: What's the difference between 'git pull' and 'git fetch'?
#6Git isn't complicated, you just have to understand that a git repository is composed of two things:
1) The index which is the git information about all your files (ie. .git/)
2) The files you currently have checked out.
When you git fetch, you update the index, nothing else.
When you git merge or git rebase or reset or checkout, you update your files from the index.
-____-
It makes me extremely sad to see this repeated over and over and people don't get it.
Re: What's the difference between 'git pull' and 'git fetch'?
#7Why do so many people have such trouble with this simple concept? Git isn't complicated, you just have to understand that a git repository is composed of two things: 1) The index which is the git information about all your files (ie. .git/) 2) The files you currently have checked out. When you git fetch, you update the index, nothing else. When you git merge or git rebase or reset or checkout, you update your files f…
Your description misses (or conflates) an entire tree of information (the HEAD tree), and it's arguably the most important one as it holds the whole of your git repo's history.
I didn't fully understand git till I read Scott Chacon's "A Tale of 3 Trees" which explains what reset is all about and goes into the details: http://git-scm.com/blog/2011/07/11/reset.html
I love git, but I do not think it's obvious or intuitive without some explanation. It's different than any other SCM I've used in the past. I created this presentation a while ago that I think highlights some of the real concepts that people need to know to really understand git: http://tednaleid.github.io/showoff-git-core-concepts/
Re: What's the difference between 'git pull' and 'git fetch'?
#8Why do so many people have such trouble with this simple concept? Git isn't complicated, you just have to understand that a git repository is composed of two things: 1) The index which is the git information about all your files (ie. .git/) 2) The files you currently have checked out. When you git fetch, you update the index, nothing else. When you git merge or git rebase or reset or checkout, you update your files f…
Re: What's the difference between 'git pull' and 'git fetch'?
#9Now let's pop the hood.
Git commit history is represented by a graph. Typically each commit has a pointer to a single parent. When history diverges and needs to be merged, a merge commit is created which has two parents (it can have more than two but such a commit is extremely atypical). The first commit obviously has no parents and is also called a root commit.
Okay, so we've got a history of commits pointing to each other in a directed acyclic graph. Now we want to traverse that graph with "git log". Where do we start? This is what branches are, a mapping from a name to a particular commit. Git stores the branch names under .git/refs/heads. Go look. These are just files whose names are the branch names, and whose values are the SHA-1 of a particular commit. (For performance reasons, git will occasionally remove the files and instead use .git/packed-refs. But again this is a file you can go cat.)
Now, there are two types of branches: 1) local branches; 2) remote branches. Local branches are just the names (those things under refs/heads) which git updates whenever you create a new commit. Remote branches are the things which git updates when you perform a git fetch. That's it.
So a fetch operation examines a remote repo's local branches (refs/heads), examines the corresponding remote branches in your repo (refs/remotes/), pulls over the differences, then updates your remote branch to match the remote's local branches. It does so according to .git/config with a section that looks like this:
[remote "origin"]
url = https://github.com/gitster/git.git
fetch = +refs/heads/master:refs/remotes/origin/master
That "fetch =" line tells git what to do when you invoke "git fetch" or "git fetch origin". It says to update your repo's refs/remotes/origin/master to match refs/heads/master in gitster's repo on github. The "+" at the start means to force it to happen even if the remote end has been rewritten (that is, the remote master's history does not "contain" refs/remotes/origin/master on your end). When you invoke git fetch you can see this happen in its output: From https://github.com/gitster/git
52a3e01..edca415 master -> origin/master
Well what happened here? Fetch examined refs/remotes/origin/master in my repo and refs/heads/master in gitster's repo, pulled over the commits I was missing, then updated my refs/remotes/origin/master (aka origin/master) from 52a3e01 to edca415. So "git log 52a3e01..edca415" will show me exactly the commits that fetch just brought over.You'd typically perform a git fetch on its own so that you can then do something like "git log master..origin/master" which tells git to show you all the commits that are in refs/remotes/origin/mater but that are NOT in refs/heads/master, i.e. exactly those commits you either need to merge in or rebase upon.
So that's fetch.
Git pull then invokes either merge or rebase. To talk about these let's add some history.
Pretend your local repo started as a clone. The remote repo ("origin") has a single branch, master, and at the time you cloned it there was a single commit on master, A. So your local repo after the clone:
refs/heads/master: A
refs/remotes/origin/master: A
Now you create a new commit: refs/heads/master: B
refs/remotes/origin/master: A
Someone else pushes a new commit to the clone and you fetch that commit: refs/heads/master: B
refs/remotes/origin/master: C
Now we have a case where history has diverged. Two people have created commits, both which have the same parent commit A, and we need to tie these both into master. Let's do it with a merge first: refs/heads/master: D
refs/remotes/origin/master: C
But what is "D"? D is a merge commit with two parents, B and C. And because D "contains" C, you can push it to the remote repo, updating refs/heads/master in the remote repo.But what if instead you want to rebase?
refs/heads/master: B'
refs/remotes/origin/master: C
This has linearized history. B' has a single parent, C, whose parent is A.Similar to creating the merge, you can push B' to the remote repo because B' contains C (unlike the original B). The rebase operation "rewrote" refs/heads/master, dropping the original B which had A as its parent and replacing it with B', which has C as its parent. Your original B is still in your repo btw, and will be there for some time until "git gc" removes it. You can find the original B in your ref log.
Re: What's the difference between 'git pull' and 'git fetch'?
#10Wow, after reading a dozen or so responses, I still don't really get it.
So there's an extra stage to think about; rather than making changes to your local checkout and committing them to the server, in git you make changes to your local checkout, commit them to your local repository, and then push them to the remote server. But this also works in the other direction: rather than fetching changes from the server directly into your local checkout, you fetch changes from the server to your local repository, then from there into your local checkout. At least, if you want to. "fetch" does the first of these, while "pull" does both of them together.
Now, you can naturally ask why we would ever want this additional complexity, but as I said at the start it's the whole point of a DVCS. Conceptually, your repository on github and your local repository are the same kind of thing, rather than a client/server relationship. You can use git without using remotes at all, in which case you'd never use push, fetch or pull; in that mode it behaves rather like SVN (just with the repository being on the same machine as the checkout). Conversely, you can use it in truly distributed fashion, where there are several federated repositories, none of which is physically distinguished from the other. At that point there is no real notion of committing to the "canonical" repository, because there isn't one, but what you can do is commit to, and checkout from, your local repository, and you can synchronize your repository with another repository in either direction (i.e. you can send commits from your repository to another, or receive commits from another repository to yours). When using it in this fashion it becomes very important that these are different operations and you want to be able to manually control when each step happens.