Skip to content

Instantly share code, notes, and snippets.

@x-yuri
Last active February 21, 2023 16:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save x-yuri/20f24f628db1bcbf272c055b33c18889 to your computer and use it in GitHub Desktop.
Save x-yuri/20f24f628db1bcbf272c055b33c18889 to your computer and use it in GitHub Desktop.
git: push.default

git: push.default

  • upstream: push the current branch to @{upstream}
  • simple: push the current branch to @{upstream} if the name and the remote matches; when the destination remote is specified, acts as current
  • current: push the current branch to the matching branch in the remote repository, ignore @{upstream}
  • matching: for each local branch push it to the matching branch if it exists remotely

"Matching" means local and remote names are equal.

The following script helps examine how it works.

The state before push. There is a repository a and 2 remotes (a.git, a2.git). The history in remotes:

* ffa0023 (a) aa
| * 974cfaf (b) ba
|/  
| * ba91b94 (c) ca
|/  
| * 4e3394d (d) da
|/  
* 73fc7d7 (HEAD -> master) ma

The local branches: master, a, b (tracks origin/b), cc (tracks origin/c), e.

There're extra commits on every local branch:

* 90f5f3b (a) ab
* ffa0023 (origin2/a, origin/a) aa
| * 88f998d (b) bb
| * 974cfaf (origin2/b, origin/b) ba
|/  
| * eefe9cd (cc) cb
| * ba91b94 (origin2/c, origin/c) ca
|/  
| * e47fff0 (e) ea
|/  
| * f6f2fd2 (HEAD -> master) mb
|/  
| * 4e3394d (origin2/d, origin/d) da
|/  
* 73fc7d7 (origin2/master, origin/master) ma
$ ./a.sh matching --from master --to origin   # push master, a, b
$ ./a.sh matching --from a      --to origin   # push master, a, b
$ ./a.sh matching --from b      --to origin   # push master, a, b
$ ./a.sh matching --from cc     --to origin   # push master, a, b
$ ./a.sh matching --from e      --to origin   # push master, a, b
$ ./a.sh matching --from master --to origin2  # push master, a, b
$ ./a.sh matching --from a      --to origin2  # push master, a, b
$ ./a.sh matching --from b      --to origin2  # push master, a, b
$ ./a.sh matching --from cc     --to origin2  # push master, a, b
$ ./a.sh matching --from e      --to origin2  # push master, a, b

$ ./a.sh current --from master --to origin   # push master -> master
$ ./a.sh current --from a      --to origin   # push a -> a
$ ./a.sh current --from b      --to origin   # push b -> b
$ ./a.sh current --from cc     --to origin   # push cc -> cc
$ ./a.sh current --from e      --to origin   # push e -> e
$ ./a.sh current --from master --to origin2  # push master -> master
$ ./a.sh current --from a      --to origin2  # push a -> a
$ ./a.sh current --from b      --to origin2  # push b -> b
$ ./a.sh current --from cc     --to origin2  # push cc -> cc
$ ./a.sh current --from e      --to origin2  # push e -> e

$ ./a.sh upstream --from master --to origin   #- no upstream
$ ./a.sh upstream --from a      --to origin   #- no upstream
$ ./a.sh upstream --from b      --to origin   # push b -> b
$ ./a.sh upstream --from cc     --to origin   # push cc -> c
$ ./a.sh upstream --from e      --to origin   #- no upstream
$ ./a.sh upstream --from master --to origin2  #- origin2 is not the upstream
$ ./a.sh upstream --from a      --to origin2  #- origin2 is not the upstream
$ ./a.sh upstream --from b      --to origin2  #- origin2 is not the upstream
$ ./a.sh upstream --from cc     --to origin2  #- origin2 is not the upstream
$ ./a.sh upstream --from e      --to origin2  #- origin2 is not the upstream

$ ./a.sh simple --from master --to origin   #- no upstream
$ ./a.sh simple --from a      --to origin   #- no upstream
$ ./a.sh simple --from b      --to origin   # push b -> b
$ ./a.sh simple --from cc     --to origin   #- the names doesn't match
$ ./a.sh simple --from e      --to origin   #- no upstream
$ ./a.sh simple --from master --to origin2  # push master -> master
$ ./a.sh simple --from a      --to origin2  # push a -> a
$ ./a.sh simple --from b      --to origin2  # push b -> b
$ ./a.sh simple --from cc     --to origin2  # push cc -> cc
$ ./a.sh simple --from e      --to origin2  # push e -> e
#!/bin/sh -eu
push_default=$1
from=$3
push_origin=$5
mkcommit() {
echo "$1" > "$1"; git add "$1"; git commit -m "$1"
}
git_log() {
git --no-pager log --graph --oneline --all
}
set -x
rm -rf a a.git a2.git
mkdir a
(cd a
git init
mkcommit ma
git checkout -b a
mkcommit aa
git checkout -b b master
mkcommit ba
git checkout -b c master
mkcommit ca
git checkout -b d master
mkcommit da
git checkout master
)
git clone --bare a a.git
git clone --bare a a2.git
rm -rf a
mkdir a
(cd a
git init
git remote add origin ../a.git
git remote add origin2 ../a2.git
git fetch origin
git fetch origin2
git reset --hard origin/master
git branch --no-track a origin/a
git branch b origin/b
git branch cc origin/c
git config push.default "$push_default"
mkcommit mb
git checkout a
mkcommit ab
git checkout b
mkcommit bb
git checkout cc
mkcommit cb
git checkout -b e --no-track origin/master
mkcommit ea
git checkout "$from"
if [ "$push_origin" = origin ]; then
git push
else
git push "$push_origin"
fi
read
cat .git/config
git --no-pager branch -a
git_log
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment