git pull
:
- runs
git fetch
; then
- (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:
- 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.