Skip to main content
19 of 31
added 689 characters in body
mfaani
  • 37.1k
  • 20
  • 196
  • 331

In simple terms, if you were about to hop onto a plane without any Internet connection...before departing you could just do git fetch origin <master>. It would fetch all the changes into your computer, but keep it separate from your local development/workspace.

On the plane, you could make changes to your local workspace and then merge it with what you've fetched and resolve potential merge conflicts all without a connection to the Internet. And unless someone had made new conflicting changes to the remote repository then once you arrive at the destination you would do git push origin <branch> and go get your coffee.


From this awesome Atlassian tutorial:

The git fetch command downloads commits, files, and refs from a remote repository into your local repository.

Fetching is what you do when you want to see what everybody else has been working on. It’s similar to SVN update in that it lets you see how the central history has progressed, but it doesn’t force you to actually merge the changes into your repository. Git isolates fetched content as a from existing local content, it has absolutely no effect on your local development work. Fetched content has to be explicitly checked out using the git checkout command. This makes fetching a safe way to review commits before integrating them with your local repository.

When downloading content from a remote repository, git pull and git fetch commands are available to accomplish the task. You can consider git fetch the 'safe' version of the two commands. It will download the remote content, but not update your local repository's working state, leaving your current work intact. git pull is the more aggressive alternative, it will download the remote content for the active local branch and immediately execute git merge to create a merge commit for the new remote content. If you have pending changes in progress this will cause conflicts and kickoff the merge conflict resolution flow.


With git pull:

  • You don't get any isolation.
  • It affects your local development.
  • It doesn't need to be explicitly checked out. Because it implicitly does a git merge.
  • It's basically NOT safe. It's aggressive.
  • Unlike git fetch where it only affects your .git/refs/remotes, git pull will affect both your .git/refs/remotes and .git/refs/heads/

###Hmmm...so if I'm not updating the working copy with git fetch, then where am I making changes? Where does Git fetch store the new commits?

Great question. It puts it somewhere isolated from your working copy. But again where? Let's find out.

In your project directory (i.e., where you do your git commands) do:

  1. ls. This will show the files & directories. Nothing cool, I know.

  2. Now do ls -a. This will show dot files, i.e., files beginning with . You will then be able to see a directory named: .git.

  3. Do cd .git. This will obviously change your directory.

  4. Now comes the fun part; do ls. You will see a list of directories. We're looking for refs. Do cd refs.

  5. It's interesting to see what's inside all directories, but let's focus on two of them. heads and remotes. Use cd to check inside them too.

  6. Any git fetch that you do will update items in the /.git/refs/remotes directory. It won't update anything in the /.git/refs/heads directory.

  7. Any git pull will first do the git fetch, update items in the /.git/refs/remotes directory, then merge with your local and then change the head inside the /.git/refs/heads directory.


A very good related answer can also be found in Where does 'git fetch' place itself?.

Also, look for "Slash notation" from the Git branch naming conventions post. It helps you better understand how Git places things in different directories.


To see the actual difference

Just do:

git fetch origin master
git checkout master

If the remote master was updated you'll get a message like this:

Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

If you didn't fetch and just did git checkout master then your local git wouldn't know that there are 2 commits added. And it would just say:

Already on 'master'
Your branch is up to date with 'origin/master'.

But that's outdated and incorrect. It's because git will give you feedback solely based on what it knows. It's oblivious to new commits that it hasn't pulled down yet...


Is there any way to see the new changes made in remote while working on the branch locally?

Some IDEs (e.g. Xcode) are super smart and use the result of a git fetch and can annotate the lines of code that have been changed in remote branch of your current working branch. If that line has been changed by both local changes and remote branch, then that line gets annotated with red. This isn't a merge conflict. It's a potential merge conflict. It's a headsup that you can use to resolve the future merge conflict before doing git pull from the remote branch.

enter image description here


Fun tip:

If you fetched a remote branch e.g. did:

git fetch origin feature/123

Then this would go into your remotes directory. It's still not available to your local directory. However, it simplifies your checkout to that remote branch by DWIM (Do what I mean):

git checkout feature/123

you no longer need to do:

git checkout -b feature/123 origin/feature/123

For more on that read here

mfaani
  • 37.1k
  • 20
  • 196
  • 331