Skip to content

Instantly share code, notes, and snippets.

@x-yuri
Last active December 15, 2024 01:29
Show Gist options
  • Save x-yuri/4c3c7e4611131a53417d7b68509b8bd8 to your computer and use it in GitHub Desktop.
Save x-yuri/4c3c7e4611131a53417d7b68509b8bd8 to your computer and use it in GitHub Desktop.
git: branch.autoSetupMerge

git: branch.autoSetupMerge

branch.autoSetupMerge makes git branch, git switch and git checkout set upstream for branches they create:

  • false - no upstream is set

  • simple - upstream is set to <start-point> when <start-point> is a remote-tracking branch and the branch names (the one to be created and the remote one) match

    On a side note, one can't create a local branch, which name matches the name of another local branch, as such one might say that if the branch names match, <start-point> can't be a local branch, i.e. <start-point> is a remote-tracking branch.

  • true (default) - upstream is set to <start-point> when <start-point> is a remote-tracking branch

  • always - upstream is set to <start-point> regardless, be <start-point> a local or remote-tracking branch, or be the branch names matching or not

  • inherit - copy upstream configuration to the branch to be created if <start-point> has an upstream

To set upstream <start-point> must not be a hash or something.

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 "doesn't set the upstream if <start-point> is a commit hash" {
    mk_cloned_repo
    git config branch.autoSetupMerge always
    branch=master start_point=origin/master

    git checkout -b "$branch" "`git rev-parse "$start_point"`"

    refute_upstream "$branch"
}

@test "doesn't set the upstream if branch.autoSetupMerge = false" {
    mk_cloned_repo
    git config branch.autoSetupMerge false
    branch=master start_point=origin/master

    git checkout -b "$branch" "$start_point"

    refute_upstream "$branch"
}

@test "doesn't set the upstream if branch.autoSetupMerge = simple and <start-point> is a local branch" {
    mk_cloned_repo
    git config branch.autoSetupMerge simple
    branch=master start_point=dev

    git checkout -b "$branch" "$start_point"

    refute_upstream "$branch"
}

@test "doesn't set the upstream if branch.autoSetupMerge = simple, <start-point> is a remote-tracking branch and the branch names don't match" {
    mk_cloned_repo
    git config branch.autoSetupMerge simple
    branch=master start_point=origin/dev

    git checkout -b "$branch" "$start_point"

    refute_upstream "$branch"
}

@test "sets the upstream to <start-point> if branch.autoSetupMerge = simple, <start-point> is a remote-tracking branch and the branch names match" {
    mk_cloned_repo
    git config branch.autoSetupMerge simple
    branch=master start_point=origin/master

    git checkout -b "$branch" "$start_point"

    assert_upstream "$branch" "$start_point"
}

@test "doesn't set the upstream if branch.autoSetupMerge = true and <start-point> is a local branch" {
    mk_cloned_repo
    git config branch.autoSetupMerge true
    branch=master start_point=dev

    git checkout -b "$branch" "$start_point"

    refute_upstream "$branch"
}

@test "sets the upstream to <start-point> if branch.autoSetupMerge = true, <start-point> is a remote-tracking branch and the branch names don't match" {
    mk_cloned_repo
    git config branch.autoSetupMerge true
    branch=master start_point=origin/dev

    git checkout -b "$branch" "$start_point"

    assert_upstream "$branch" "$start_point"
}

@test "sets the upstream to <start-point> if branch.autoSetupMerge = true, <start-point> is a remote-tracking branch and the branch names match" {
    mk_cloned_repo
    git config branch.autoSetupMerge true
    branch=master start_point=origin/master

    git checkout -b "$branch" "$start_point"

    assert_upstream "$branch" "$start_point"
}

@test "sets the upstream to <start-point> if branch.autoSetupMerge = always and <start-point> is a local branch" {
    mk_cloned_repo
    git config branch.autoSetupMerge always
    branch=master start_point=dev

    git checkout -b "$branch" "$start_point"

    assert_upstream "$branch" "$start_point"
}

@test "sets the upstream to <start-point> if branch.autoSetupMerge = always, <start-point> is a remote-tracking branch and the branch names don't match" {
    mk_cloned_repo
    git config branch.autoSetupMerge always
    branch=master start_point=origin/dev

    git checkout -b "$branch" "$start_point"

    assert_upstream "$branch" "$start_point"
}

@test "sets the upstream to <start-point> if branch.autoSetupMerge = always, <start-point> is a remote-tracking branch and the branch names match" {
    mk_cloned_repo
    git config branch.autoSetupMerge always
    branch=master start_point=origin/master

    git checkout -b "$branch" "$start_point"

    assert_upstream "$branch" "$start_point"
}

@test "doesn't set the upstream if branch.autoSetupMerge = inherit and <start-point> doesn't have an upstream" {
    mk_cloned_repo
    git config branch.autoSetupMerge inherit
    branch=master start_point=dev
    git branch --unset-upstream "$start_point"

    git checkout -b "$branch" "$start_point"

    refute_upstream "$branch"
}

@test "copies the upstream configuration if branch.autoSetupMerge = inherit and <start-point> has an upstream" {
    mk_cloned_repo
    git config branch.autoSetupMerge inherit
    branch=master start_point=dev

    git checkout -b "$branch" "$start_point"

    assert_upstream "$branch" "`git rev-parse --abbrev-ref "$start_point@{upstream}"`"
}

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
}

mk_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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment