branch.<name>.remote
and branch.<name>.merge
together define the upstream branch for the given branch (if they're set, the given branch has an upstream branch). .
as a remote denotes the local repository.
E.g. if branch.dev.remote = origin
and branch.dev.merge = refs/heads/dev
, then origin/dev
(the remote-tracking branch of the remote branch dev
) is an upstream of dev
.
Or if branch.a.remote = .
and branch.a.merge = refs/heads/b
, then b
is an upstream of a
.
The upstream branch tells (under certain circumstances):
git fetch
which branch to fetch and/or from which remotegit pull
which branch to merge (which branch to rebase onto)git push
which remote to push to and/or to which branch
The relevant docs:
branch.<name>.remote
When on branch
<name>
, it tellsgit fetch
andgit push
which remote to fetch from or push to. The remote to push to may be overridden withremote.pushDefault
(for all branches). The remote to push to, for the current branch, may be further overridden bybranch.<name>.pushRemote
. If no remote is configured, or if you are not on any branch and there is more than one remote defined in the repository, it defaults toorigin
for fetching andremote.pushDefault
for pushing. Additionally,.
(a period) is the current local repository (a dot-repository), seebranch.<name>.merge
's final note below.
https://git-scm.com/docs/git-config#Documentation/git-config.txt-branchltnamegtremote
branch.<name>.merge
Defines, together with
branch.<name>.remote
, the upstream branch for the given branch. It tellsgit fetch
/git pull
/git rebase
which branch to merge and can also affectgit push
(seepush.default
). When in branch<name>
, it tellsgit fetch
the default refspec to be marked for merging inFETCH_HEAD
. The value is handled like the remote part of a refspec, and must match a ref which is fetched from the remote given by"branch.<name>.remote"
. The merge information is used bygit pull
(which first callsgit fetch
) to lookup the default branch for merging. Without this option,git pull
defaults to merge the first refspec fetched. Specify multiple values to get an octopus merge. If you wish to setupgit pull
so that it merges into<name>
from another branch in the local repository, you can pointbranch.<name>.merge
to the desired branch, and use the relative path setting.
(a period) forbranch.<name>.remote
.
https://git-scm.com/docs/git-config#Documentation/git-config.txt-branchltnamegtmerge
When no remote is specified, by default the
origin
remote will be used, unless there’s an upstream branch configured for the current branch.
https://git-scm.com/docs/git-fetch#_description
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
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
.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.
https://git-scm.com/docs/git-pull#_examples
When the command line does not specify where to push with the
<repository>
argument,branch.*.remote
configuration for the current branch is consulted to determine where to push. If the configuration is missing, it defaults toorigin
.
https://git-scm.com/docs/git-push#_description
git push
Works like
git push <remote>
, where<remote>
is the current branch’s remote (ororigin
, if no remote is configured for the current branch).git push origin
Without additional configuration, pushes the current branch to the configured upstream (
branch.<name>.merge
configuration variable) if it has the same name as the current branch, and errors out without pushing otherwise.The default behavior of this command when no
<refspec>
is given can be configured by setting the push option of the remote, or thepush.default
configuration variable.For example, to default to pushing only the current branch to origin use
git config remote.origin.push HEAD
. Any valid<refspec>
(like the ones in the examples below) can be configured as the default forgit push origin
.
https://git-scm.com/docs/git-push#_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 (2 commits, 1 local branch dev):
# a (origin/master) --- b (HEAD -> dev, origin/dev)
@test "branch with an upstream has branch.<name>.remote and branch.<name>.merge set" {
start_cloned_repo
assert_equal "`git config branch.dev.remote`" origin
assert_equal "`git config branch.dev.merge`" refs/heads/dev
assert_upstream dev origin/dev
}
@test "branch without an upstream doesn't have branch.<name>.remote and branch.<name>.merge set" {
start_cloned_repo
git checkout -b feature
assert_equal "`git config branch.feature.remote`" ''
assert_equal "`git config branch.feature.merge`" ''
refute_upstream feature
}
@test "can't set an upstream branch when no remote.<name>.fetch" {
start_cloned_repo
git config unset remote.origin.fetch
run git branch -u origin/dev
assert_equal "$status" 128
assert_output -p "fatal: cannot set up tracking information; starting point 'origin/dev' is not a branch"
}
assert_upstream() {
run git rev-parse --abbrev-ref "$1@{upstream}"
assert_output "$2"
}
refute_upstream() {
run git rev-parse --abbrev-ref "$1@{upstream}"
if [ "${2-}" ]; then
refute_output "$2"
else
assert_output "fatal: no upstream configured for branch '$1'"
fi
}
start_cloned_repo() {
(mkrepo)
cd "$BATS_TEST_TMPDIR"
git clone a b
cd b
}
mkrepo() {
cd "$BATS_TEST_TMPDIR"
mkdir a
cd a
git init
git config user.email [email protected]
git config user.name "Your Name"
git commit --allow-empty -m a
git checkout -b dev
git commit --allow-empty -m b
}
$ 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