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 fetchwhich branch to fetch and/or from which remotegit pullwhich branch to merge (which branch to rebase onto)git pushwhich remote to push to and/or to which branch
The relevant docs:
branch.<name>.remoteWhen on branch
<name>, it tellsgit fetchandgit pushwhich 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 tooriginfor fetching andremote.pushDefaultfor 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>.mergeDefines, together with
branch.<name>.remote, the upstream branch for the given branch. It tellsgit fetch/git pull/git rebasewhich branch to merge and can also affectgit push(seepush.default). When in branch<name>, it tellsgit fetchthe 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 pulldefaults to merge the first refspec fetched. Specify multiple values to get an octopus merge. If you wish to setupgit pullso that it merges into<name>from another branch in the local repository, you can pointbranch.<name>.mergeto 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
originremote 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 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.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.
https://git-scm.com/docs/git-pull#_examples
When the command line does not specify where to push with the
<repository>argument,branch.*.remoteconfiguration 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 pushWorks like
git push <remote>, where<remote>is the current branch’s remote (ororigin, if no remote is configured for the current branch).git push originWithout additional configuration, pushes the current branch to the configured upstream (
branch.<name>.mergeconfiguration 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.defaultconfiguration 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