3

I am new in Git and I have used git pull origin <my-branch> in most of the time to get the changes from remote repository.

However, as I get some experience, I have observed that git fetch is preferred more, but reading several topics e.g. What is the difference between 'git pull' and 'git fetch'? and Git: Fetch and merge, don’t pull, now I am confused and need a clarification if there is a valid reason to prefer it except from checking changes before getting them.

The general idea behind this, git pull is git fetch + git merge, nut of course there are several drawbacks, etc.

So, could you please clarify me on:

1. How I should update my local branch from remote?

2. As far as I see, the difference between git pull origin <my-branch> and git pull origin, the latter gets all the branches from origin besides <my-branch>. Is that true? And which one should I prefer?

  • Does this answer your question? [What is the difference between 'git pull' and 'git fetch'?](https://stackoverflow.com/questions/292357/what-is-the-difference-between-git-pull-and-git-fetch) – sommmen Jan 25 '22 at 07:21
  • Unfortunately no, I read it but confused more :( –  Jan 25 '22 at 07:22
  • @sommmen Any clarification about this issue please? –  Jan 25 '22 at 07:23
  • I do not see any problems with `git pull` in any form. You have to just be aware what it does and if this fits your current need. – Marek R Jan 25 '22 at 07:26
  • It fits, but I want to use the most proper way. Any suggestion? –  Jan 25 '22 at 07:44

6 Answers6

5

git fetch is the command that tells your local git to retrieve the latest meta-data info from the original (yet doesn’t do any file transferring. It’s more like just checking to see if there are any changes available)

git pull on the other hand does that AND brings (copy) those changes from the remote repository.

The takeaway is to keep in mind that there generally are at least three copies of a project on your workstation.

  1. One copy is your own repository with your own commit history (the already saved one, so to say).
  2. The second copy is your working copy where you are editing and building (not committed yet to your repo).
  3. The third copy is your local “cached” copy of a remote repository (probably the original from where you cloned yours).

You can use git fetch to know the changes done in the remote repo/branch since your last pull. This is useful to allow for checking before doing an actual pull, which could change files in your current branch and working copy (and potentially lose your changes, etc).

git fetch    
git diff ...origin
  1. How I should update my local branch from remote?

Git pull is a safe way to update your branch. There will be times that a conflict will arise from pulling and these will be the edge cases. Worst case scenario you would undo the changes of git pull

  1. As far as I see, the difference between git pull origin "my-branch" and git pull origin, the latter gets all the branches from origin besides . Is that true? And which one should I prefer?

If you use git pull origin without specifying "my-branch", git will fill the value with the branch that you are currently using

Tolis Gerodimos
  • 3,782
  • 2
  • 7
  • 14
  • Good explanations, voted up ;) But I am wondering the conflict status, because if I use `git fetch` and then `git merge`, how could I prevent conflicts that I could get by using `git pull` ? –  Jan 25 '22 at 07:50
  • 1
    There are a few issues with this answer : `git fetch` *does* download the files and complete commits to your local workstation and update remote branches (e.g : `origin/branch_name`); what it *doesn't* do is change your local branches. – LeGEC Feb 11 '22 at 17:39
  • 1
    The potential problem with `git pull` is that it can mess up your local changes -- if you have any -- without giving you the opportunity to check beforehand what would happen (it runs `git fetch + git merge` in one go, and you don't know yet what `git fetch` will download). Although it is generally what you want to do, when it turns out it was bad, it is too late to revert easily. – LeGEC Feb 11 '22 at 17:42
  • If you start from a clean state (which is highly recommended before running `git pull`), you may land in conflicts you hadn't expected, but at least you can revert to the previous state of your repo. – LeGEC Feb 11 '22 at 17:45
3

git pull:

  1. runs git fetch; then
  2. (without waiting for you to confirm!) runs a second Git command.

If you want to run two Git commands, and the second command that git pull will run is the command that you want to run second, git pull is fine.

I personally often like to insert some additional Git command(s) between the fetch command and the other command. This is impossible to do when using git pull, because it does not pause for you. So I often avoid git pull. (In particular, I often want to run git log to see what I'm getting into.)

I also find that for those new to Git, they think git pull is sort of magical. By avoiding it—at least initially—in favor of the two separate steps, they learn how to use Git. When using git pull, they don't learn how to use Git. (This applied to me back in 2005 or so too.) So I encourage newbies to use the separate commands. This helps not only with the "Git isn't magic" part, but also with the fact that the second command that git pull runs is something you choose:

  • You can choose to have git pull run git merge.
  • You can choose to have git pull run git rebase.

These two commands both combine work, but the way they do it is very different. If you have done no work in your repository, combine the work I did, i.e., nothing, with the work someone else did results in getting the work that someone else did, so it doesn't matter which command you used. But if you did do some work in your repository, it does matter.

This, too, stands out much better when you separate out the two commands:

  • git merge means merge my work with their work: merge "nothing" with "something" = "something"; merge "something" with "something else" = "some third thing".
  • git rebase means redo my work atop their work: redo "nothing" atop "something" = "something", but redo something atop something else, well, you can probably see where this is going (but if not, read up on git rebase).

To answer your specific questions:

  1. How I should update my local branch from remote?

That depends on which result you want and how sure you are about that second command.

As far as I see, the difference between git pull origin <my-branch> and git pull origin, the latter gets all the branches from origin besides <my-branch>. Is that true?

Mostly. This is where we really need to break git pull down into its two steps, and observe what it gives to each of the two steps.

When you run git pull, you can provide options. For instance, these are both valid ways to invoke git pull:

git pull --rebase

git pull --ff-only

These options are contradictory because --rebase says that git pull should run git rebase as its second command, while --ff-only says that git pull should supply the --ff-only option to the git merge second command, implying that it should run git merge, not git rebase.

So some options control which second command pull should use. Other options are passed to the second command. Still other options are passed to the first, git fetch, command. It's all a bit confusing, and is yet another reason to learn git fetch first.

You can also provide arguments, such as the <my-branch> you suggested here. All non-option arguments you provide are passed to git fetch. Arguments are distinguished from options by the - or -- that goes in front of an option. (Single-dash - options are single letters, such as -j or -4; double-dash -- options are multiple letters, such as --rebase and --show-forced-updates.)

If you provide arguments like origin and <my-branch>, these go through to git fetch, and this affects how git fetch operates. With no arguments, git fetch will:

  • Find the right remote to call up (generally origin): a "remote" is a short name for a way to reach some other Git software that will, in this case, read from another Git repository. In this case you're reaching out to some Git software on GitHub or Bitbucket or GitLab, perhaps, where there's the Git repository from which you made your Git repository earlier. You'd like to reach out to that same Git repository now, and find out if they have any new commits that your Git repository does not yet have. (How did those commits get there? Well, we can worry about that later.)

  • Call up that software and connect to that repository. That repository has its branches and its commits. The branches in that repository are not your branches! They are their branches. They may store different commit hash IDs in them.

  • Figure out which commits they have that you don't, based on the hash IDs stored in their branch names. Decide which commits you want in your repository.

If you don't list some branch name(s) on the git fetch command, your Git assumes you want to update all your copies of all of their branches. So your Git will inspect their master or main, and their develop, and their feature/short or feature/long or feature/tall or whatever. Your Git will figure out if they have any new commits that you don't, and will bring those commits over into your Git repository.

Because commits are numbered with universally unique identifiers, your Git (your software operating on your repository) will now have all of their commits, using the same numbers they are using. Your Git will also have all your own commits that they don't have at all. Now that your Git has all their commits, your Git will create or update all your remote-tracking names: origin/main or origin/master for their main or master, origin/develop for their develop, and so on. Your Git builds these names by sticking the remote name, origin, in front of each of their branch names.

These remote-tracking names constitute your Git's memory of where their branches were, the last time you got hold of their Git. So git fetch with no arguments updates all of them, and since git pull with no arguments calls git fetch with no arguments, you get all your origin/* names updated. With one argument—git pull origin—the same thing happens, you're just now being explicit that you want to work with the remote named origin. If that's the only remote that you have—and that's a typical setup—this does exactly the same thing; any other name here, like git fetch belgium or something, just gives you an error.

But if you run git fetch origin develop, that tells your Git that, for the purpose of this one git fetch operation, you'd like your Git to call up their Git, see all their branches, but limit your updates to any commits needed to update your origin/develop. If they have a new commit on their main, you won't update your origin/main after all. (You'll almost certainly want or have to do that later, so this doesn't really save you much. In fact it might take more time later, vs doing it all at once, due to the way Git optimizes fetching. But it's there if you want it.)

Since git pull passes all the arguments on, git pull origin develop directs your git fetch step to limit itself to their branch named develop. (Again, this becomes your origin/develop.)

But now the second command comes into play. Having run git fetch, with whatever extra options and arguments it might have used, your git pull now runs the second command you chose. (You did choose one, right? Always make sure you know which second command Git will run here! Most people set one up semi-permanently, so that they know.) This second command is either:

git rebase [options argument(s)]

or:

git merge options argument(s)

Git's pull often passes some options and/or arguments here. In particular, for git merge, it passes:

-m "merge branch '<branch>' of <url>"

to set the merge message, and then it passes the raw hash ID of the tip commit you brought in. For rebase, it may pass --autostash, and it may pass a commit hash ID (or it can let rebase figure out @{upstream} on its own). You don't really need to know all this, but it's worth remembering that git pull does some extra stuff especially for the git merge case, to set the merge message.

There's one last caveat here:

git pull origin br1 br2

is tempting to newbies. Do not use it. It runs git fetch origin br1 br2 and then runs an octopus merge (of HEAD, origin/br1, and origin/br2, in effect) and unless you really know what you're doing, you don't want an octopus merge.

This results in several bottom lines

If you set git pull to always run git rebase, there's very little difference between running your own git fetch followed by your own git rebase, and just running git pull. That's because there's no merge message to alter. Be sure you know what rebase does before you do this, though: rebase is more complicated than merging.

If you set git pull to always run git merge, the fetch-then-merge that pull does has the advantage (?) of setting the merge message to something that might be slightly better than the default you'd get with two separate commands. Compare:

merge branch 'smörgåsbord' of ssh://github.com/swedish/meatballs.git

vs:

merge branch 'origin/smörgåsbord'

Neither one really tells you anything useful, but some might like one better than the other.

Watch out for git pull <remote> <branch1> <branch2>, which is almost certain to do the wrong thing (though if you're set up to rebase, this should just give you an error; rebasing does not make sense with this case).

If you want to run a command between two commands (such as git log) in order to choose which second command to use, you cannot use the do-it-all-at-once leap-before-you-look git pull. This is why—and when—I avoid git pull.

Other than that, they're pretty much the same thing, once you know how git pull just runs two Git commands for you.

torek
  • 448,244
  • 59
  • 642
  • 775
  • Thanks a lot this wonderful explanations. I generally avoid rebase as I have not enough experience. So, I decide to use fetch by merge. In this case, I am wondering if people use `fetch` by following `merge` or is there a settings when running fetch then it automatically executes merge as @VonC suggest? –  Jan 25 '22 at 13:08
  • There is no such setting. However, sometimes `git merge` performs a fast-forward operation *instead of* a merge, and `git fetch` *can* perform fast-forwards. But don't do this until you're very familiar with what all of this means and how Git uses *refs* and *refspecs*. I actually like `git pull` to perform fast-forward-only operations, failing the merge when not; and since Git 2.29 there is a setting for *that* now, but it was somewhat broken until 2.34. So I don't normally write about it here: it's too new. – torek Jan 26 '22 at 01:45
  • Then if I want to use `git fetch`, then I should use it via the following 2 commands: `git fetch origin ` and then (when I am on this feature-branch, `git merge `. Is that true? –  Jan 26 '22 at 07:38
  • I use: `git fetch`, and then `git merge`. This does depend on one thing, which is that the *current branch* needs to have what Git calls an *upstream* set. Without that, I recommend `git fetch` (with no additional arguments) and `git merge origin/somebranch`. Note that you need to provide the *local memory name* of the branch as seen in the other Git, when using the split-up variant. You provide the *other Git's name* of the branch as seen in the other Git when using the `git pull origin somebranch` variant. – torek Jan 26 '22 at 07:55
1

I am new in Git and I have used git pull origin in most of the time to get the changes from remote repository.

They are different commands that do different things, fetch loads all new remote commits. you can then review them and when you know want to actually apply all those new remote commits to your local branch you run a pull.

To be clear running a pull is the equivalent of running a fetch and then a merge merging the remote changes to local.

now I am confused and need a clarification if there is a valid reason to prefer it except from checking changes before getting them.

You don't use the one ore the other - you use them both. There is no preference - you fetch and then you pull - or you just pull.

The preference you're seeing likely comes from the fact that fetch is a safe operation - it changes nothing. Pull does change your local files and you could end up with merge conflicts.

  1. How I should update my local branch from remote?

Running a pull on a local feature branch is fine, but there may be merge commits.

  1. As far as I see, the difference between git pull origin and git pull origin, the latter gets all the branches from origin besides . Is that true? And which one should I prefer?

Not sure about that one.

sommmen
  • 6,570
  • 2
  • 30
  • 51
  • Thanks a lot, voted up. But "Running a pull on a local feature branch is fine, but there may be merge commits." --> If I use fetch, will I not get these conflicts? What is the difference? Do you mean that if I use fetch, I will merge commit by commit in the fetched branch to my local branch? –  Jan 25 '22 at 07:41
  • @Owl fetch only update the remote tacking branches. It never changes anything in your local branches. So no conflict possible, since there is no merge or rebase done by a fetch. – VonC Jan 25 '22 at 08:02
0

I am not Writing it based on document but based on some experience. its not much but it might help.

  1. Git pull is the command you should use to get the code in remote to your local.
  2. git fetch only get the meta data not the actual code.

In general with single repo you will never encounter fetch command being used, but if you are working on fork or have multiple remote repo, then only fetch is useful or being used frequently.

Mayank Jain
  • 436
  • 3
  • 13
  • Yes, these are the points that I have observed. But, I am not sure why I should prefer `git fetch` + `git merge` instead of `git pull`? –  Jan 25 '22 at 07:29
  • What about my 2nd question? –  Jan 25 '22 at 07:29
  • @ManyakJain Amigo? Any reply please? –  Jan 25 '22 at 07:41
  • I think you should do more work in understanding some common point, and try for visual git so u can better understand, bcoz fetch, merge and pull are completely different concept and u will only get them if u have some clear idea and clear picture. you should definitely see it in visual git so to get it. – Mayank Jain Jan 27 '22 at 11:10
  • @ManyakJain Thanks a lot amigo. DO you suggest some plugins that displays git branches in colour in VSCode or IntelliJ? –  Jan 27 '22 at 14:01
  • just search for this "visualizing git" in google, u will get lots of site for this which show all your practice in graphical format side by side. Practice there, this will help u learn and understand better. – Mayank Jain Jan 27 '22 at 15:19
0

How I should update my local branch from remote?

I always use git pull (which be default fetch all branches).

But I first set, since Git 2.6

git config --global pull.rebase true
git config --global rebase.autoStash true

That way, after fetching, a simple git pull triggers a rebase of my local commits on top of the fetched remote branch.

The only disadvantage I see is the possible conflicts you might have to resolve multiple times, git pull after git pull. But that is what git rerere would prevent if you are in that case (quite rare).
See "What is git-rerere, and how does it work?"

On the advantages: see "Is it better to use git pull --rebase than git pull --ff-only".

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • **1**. Hmmm, seems very tricky and useful. I think using this approach, there is no need to use 2 commands (fetch + pull) and continue using pull by providing the advantage of fetch command. Is that true? –  Jan 25 '22 at 07:37
  • @Owl Exactly: just `git pull` is enough. – VonC Jan 25 '22 at 07:37
  • **2.** Should I run this setting for each repository for once? And may there be a disadvantage of this approach? –  Jan 25 '22 at 07:38
  • @Owl No, I set it for all repo through the `git config --global` option. It is best suited for development workflow, when you want your local commits (not pushed yet) replayed on top of the updated (fetched) upstream branch. – VonC Jan 25 '22 at 07:40
  • Could you clarify a little bit more about "when you want your local commits (not pushed yet) replayed on top of the updated (fetched) upstream branch"? –  Jan 25 '22 at 07:46
  • By the way voted up for your useful explanations ;) –  Jan 25 '22 at 07:47
  • @Owl fetch never merge, only pull would fetch + merge by default. I just prefer fetch + rebase in my case. – VonC Jan 25 '22 at 07:49
  • But you said "*I always use git pull"* in your answer. Which one do you prefer? –  Jan 25 '22 at 07:52
  • @Owl git pull, because as configured, it fetches and rebases, instead of fetching and merging. – VonC Jan 25 '22 at 07:54
  • Then I would use this config with `git pull`, but before using it could you please clarify me about the possible disadvantages of this approach? –  Jan 25 '22 at 08:13
  • @Owl Sure. I have edited the answer accordingly. – VonC Jan 25 '22 at 08:19
0

I use git fetch if I am fetching a new branch that someone else pushed. Let us suppose that I want to look at Mary's latest changes on her branch, featureB.

I would do:

git checkout featureB
git pull origin featureB

That would fetch the latest meta-data for featureB, and merge it into my current copy of featureB.

But if have never pulled featureB, then I cannot checkout featureB.

If I have currently checked out my own branch, featureA, then I do not want to perform git pull origin featureB because that would fetch featureB, and then merge it into my featureA branch.

Therefore I do this:

git fetch origin featherB
git checkout featureB

Now I have branch featureB in my local repo.

Since I now have branch featureB in my local repo, it is now possible to use checkout the next time I want to update it from the remote repo.

Suppose I had branch featureA checked out, and I want to get the latest version of featureB. I can do this:

git checkout featureB
git pull origin featureB
Randy Leberknight
  • 1,363
  • 9
  • 17
  • **1.** Good explanations, voted up. *Now have a new copy of featureB* --> Do you mean that the copy is in our local cache? –  Jan 27 '22 at 06:24
  • **2.** *Next time I can do get checkout featureB and then git pull origin featureB* --> I could not understand this. Any clarification pls? –  Jan 27 '22 at 06:24
  • I edited my original post to clarify the points you asked about. – Randy Leberknight Jan 27 '22 at 19:22