$ git pull [<repository> [<refspec>...]]
Basically does git fetch [<repository> [<refspec>...]]
+ git merge FETCH_HEAD
(git rebase FETCH_HEAD
).
If multiple <refspec>
's are passed or a <refspec>
resolves to multiple references, then all the resolved references are merged into the current branch (rebase
is possible only when one reference is to be rebased onto). If there's only one reference, it's merged into the current branch (the current branch is rebased onto it).
If no <refspec>
's are passed, then the upstream branch is merged into the current branch (the current branch is rebased onto the upstream branch).
If the current branch has no upstream branch, it fails.
The relevant docs:
Default values for
<repository>
and<branch>
are read from the "remote" and "merge" configuration for the current branch as set by git-branch[1]--track
.
https://git-scm.com/docs/git-pull#_description
<refspec>
Specifies which refs to fetch and which local refs to update. When no
<refspec>
s appear on the command line, the refs to fetch are read fromremote.<repository>.fetch
variables instead (see the section "CONFIGURED REMOTE-TRACKING BRANCHES" in git-fetch[1]).There is a difference between listing multiple
<refspec>
directly ongit pull
command line and having multipleremote.<repository>.fetch
entries in your configuration for a<repository>
and running agit pull
command without any explicit<refspec>
parameters.<refspec>
s listed explicitly on the command line are always merged into the current branch after fetching. In other words, if you list more than one remote ref,git pull
will create an Octopus merge. On the other hand, if you do not list any explicit<refspec>
parameter on the command line,git pull
will fetch all the<refspec>
s it finds in theremote.<repository>.fetch
configuration and merge only the first<refspec>
found into the current branch. This is because making an Octopus from remote refs is rarely done, while keeping track of multiple remote heads in one-go by fetching more than one is often useful.
https://git-scm.com/docs/git-pull#Documentation/git-pull.txt-ltrefspecgt
Often people use
git pull
without giving any parameter. Traditionally, this has been equivalent to sayinggit pull origin
. However, when configurationbranch.<name>.remote
is present while on branch<name>
, that value is used instead oforigin
.In order to determine what remote branches to fetch (and optionally store in the remote-tracking branches) when the command is run without any refspec parameters on the command line, values of the configuration variable
remote.<origin>.fetch
are consulted, and if there aren’t any,$GIT_DIR/remotes/<origin>
is consulted and itsPull:
lines are used. In addition to the refspec formats described in the OPTIONS section, you can have a globbing refspec that looks like this:refs/heads/*:refs/remotes/origin/*
A globbing refspec must have a non-empty RHS (i.e. must store what were fetched in remote-tracking branches), and its LHS and RHS must end with
/*
. The above specifies that all remote branches are tracked using remote-tracking branches inrefs/remotes/origin/
hierarchy under the same name.The rule to determine which remote branch to merge after fetching is a bit involved, in order not to break backward compatibility.
If explicit refspecs were given on the command line of
git pull
, they are all merged.When no refspec was given on the command line, then
git pull
uses the refspec from the configuration or$GIT_DIR/remotes/<origin>
. In such cases, the following rules apply:
If
branch.<name>.merge
configuration for the current branch<name>
exists, that is the name of the branch at the remote site that is merged.If the refspec is a globbing one, nothing is merged.
Otherwise the remote branch of the first refspec is merged.
https://git-scm.com/docs/git-pull#_default_behaviour
Update the remote-tracking branches for the repository you cloned from, then merge one of them into your current branch:
$ git pull $ git pull origin
Normally the branch merged in is the
HEAD
of the remote repository, but the choice is determined by thebranch.<name>.remote
andbranch.<name>.merge
options; see git-config[1] for details.Merge into the current branch the remote branch
next
:$ git pull origin next
This leaves a copy of
next
temporarily inFETCH_HEAD
, and updates the remote-tracking branchorigin/next
. The same can be done by invokingfetch
andmerge
:$ git fetch origin $ git merge origin/next
https://git-scm.com/docs/git-pull#_examples
a.bats
:
strict() { set -euo pipefail; shopt -s inherit_errexit; "$@"; }
setup() {
[ "$BATS_LIB_PATH" = /usr/lib/bats ] && BATS_LIB_PATH=$HOME/.bats/lib:$BATS_LIB_PATH
bats_load_library bats-support
bats_load_library bats-assert
strict
}
# the state of the cloned repository (1 commit, 1 local branch ba)
# A (HEAD -> ba, origin/ba)
@test "does an octopus merge when more than 1 reference" {
start_cloned_repo
(cd ../a && git commit --allow-empty -m B \
&& git checkout -b bb HEAD~ && git commit --allow-empty -m C)
# git pull --no-ff origin 'refs/heads/*:refs/remotes/origin/*'
git pull --no-ff origin ba bb
assert_equal "`
git show --pretty=%P -s | tr ' ' '\n' | sort
`" "`
{ git rev-parse HEAD~
git rev-parse origin/ba
git rev-parse origin/bb; } | sort
`"
}
@test "pulls the specified reference" {
start_cloned_repo
(cd ../a && git commit --allow-empty -m B)
git checkout -b bb
git pull --no-ff origin ba
assert_equal_sha HEAD^2 origin/ba
}
@test "pulls the upstream branch" {
start_cloned_repo
git push origin ba:bb; git branch -u origin/bb
(cd ../a && git checkout bb && git commit --allow-empty -m B)
git pull --no-ff origin
assert_equal_sha HEAD^2 origin/bb
}
@test "fails when no upstream branch" {
start_cloned_repo
git branch --unset-upstream
run git pull --no-ff origin
assert_equal "$status" 1
assert_output -p "`ml \
"You asked to pull from the remote 'origin', but did not specify" \
'a branch. Because this is not the default configured remote' \
'for your current branch, you must specify a branch on the command line.'`"
}
@test "fails when the upstream branch is in the other remote" {
start_cloned_repo
git remote add origin2 ../a2
run git pull --no-ff origin2
assert_equal "$status" 1
assert_output -p "`ml \
"You asked to pull from the remote 'origin2', but did not specify" \
'a branch. Because this is not the default configured remote' \
'for your current branch, you must specify a branch on the command line.'`"
}
@test "pulls from the upstream's remote" {
start_cloned_repo
(cd ../a2 && git commit --allow-empty -m B)
git remote add origin2 ../a2
git fetch origin2; git branch -u origin2/ba
git pull --no-ff
assert_equal_sha HEAD^2 origin2/ba
}
assert_equal_sha() {
assert_equal "`git rev-parse "$1"`" "`git rev-parse "$2"`"
}
assert_not_equal_sha() {
! assert_equal_sha "$1" "$2"
}
assert_branch() {
git show-ref --verify --quiet "$1"
}
refute_branch() {
run git show-ref --verify --quiet "$1"
assert_equal "$status" 1
}
start_cloned_repo() {
(mkrepos)
cd "$BATS_TEST_TMPDIR"
git clone a b
cd b
git config user.email [email protected]
git config user.name "Your Name"
}
mkrepos() {
cd "$BATS_TEST_TMPDIR"
mkdir a
(cd a
git init
git branch -m ba
git config user.email [email protected]
git config user.name "Your Name"
git commit --allow-empty -m A)
cp -r a a2
}
ml() { for l; do printf '%s\n' "$l"; done; }
$ docker run --rm -itv "$PWD":/app -w /app alpine:3.21
/ # apk add git bash ncurses
/ # git clone https://github.com/bats-core/bats-core ~/.bats
/ # git clone https://github.com/bats-core/bats-support ~/.bats/lib/bats-support
/ # git clone https://github.com/bats-core/bats-assert ~/.bats/lib/bats-assert
/ # ~/.bats/bin/bats a.bats