$ 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>.fetchvariables instead (see the section "CONFIGURED REMOTE-TRACKING BRANCHES" in git-fetch[1]).There is a difference between listing multiple
<refspec>directly ongit pullcommand line and having multipleremote.<repository>.fetchentries in your configuration for a<repository>and running agit pullcommand 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 pullwill create an Octopus merge. On the other hand, if you do not list any explicit<refspec>parameter on the command line,git pullwill fetch all the<refspec>s it finds in theremote.<repository>.fetchconfiguration 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 pullwithout giving any parameter. Traditionally, this has been equivalent to sayinggit pull origin. However, when configurationbranch.<name>.remoteis 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>.fetchare 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 pulluses the refspec from the configuration or$GIT_DIR/remotes/<origin>. In such cases, the following rules apply:
If
branch.<name>.mergeconfiguration 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 originNormally the branch merged in is the
HEADof the remote repository, but the choice is determined by thebranch.<name>.remoteandbranch.<name>.mergeoptions; see git-config[1] for details.Merge into the current branch the remote branch
next:$ git pull origin nextThis leaves a copy of
nexttemporarily inFETCH_HEAD, and updates the remote-tracking branchorigin/next. The same can be done by invokingfetchandmerge:$ 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