Skip to content

Instantly share code, notes, and snippets.

@x-yuri
Last active December 22, 2024 07:13
Show Gist options
  • Save x-yuri/a25ae25574e4b7e3b0f37cbed04e2035 to your computer and use it in GitHub Desktop.
Save x-yuri/a25ae25574e4b7e3b0f37cbed04e2035 to your computer and use it in GitHub Desktop.
git: push.default

The setting determines which local branches git push and git push <repository> should push and where. (It also affects some other cases, see git push.) To put it briefly:

  • nothing - push nothing (error out)
  • upstream - push the current branch to the upstream branch
  • simple (the default) - push the current branch to the matching (the same name) upstream branch (upstream + branch names should match)
  • current - push the current branch to the matching branch in the chosen remote
  • matching - for each local branch l, if there's a branch r in the chosen remote that has the same name, then push l to r

If push.default is current or matching, it pushes to:

If the target remote doesn't get chosen, it fails (because then there are multiple options (remotes) and no reason to choose one over the others).

If push.default is simple, it pushes to:

If push.default is upstream, the upstream branch's remote can't be overridden.

If the target remote is the local repository (because the upstream branch points to it), there can be no matching branches (a repository can't have 2 branches with the same name). This affects the last 3 modes (simple, current, matching). In this case when push.default is simple it fails, when push.default is current or matching no branches are pushed.

If push.default is current and the matching branch doesn't exist, it gets created. If push.default is matching, no branches get created.

git push fails when push.default is upstream or simple and the upstream branch is not set. When push.default is upstream it also fails when <repository> is passed, or branch.<name>.pushRemote or remote.pushDefault are set. When push.default is simple it also fails when the current and upstream branch names don't match. If push.default is current or matching, it fails when it's unable choose a remote.

The relevant docs:

push.default

Defines the action git push should take if no refspec is given (whether from the command-line, config, or elsewhere). Different values are well-suited for specific workflows; for instance, in a purely central workflow (i.e. the fetch source is equal to the push destination), upstream is probably what you want. Possible values are:

  • nothing - do not push anything (error out) unless a refspec is given. This is primarily meant for people who want to avoid mistakes by always being explicit.

  • current - push the current branch to update a branch with the same name on the receiving end. Works in both central and non-central workflows.

  • upstream - push the current branch back to the branch whose changes are usually integrated into the current branch (which is called @{upstream}). This mode only makes sense if you are pushing to the same repository you would normally pull from (i.e. central workflow).

  • tracking - This is a deprecated synonym for upstream.

  • simple - push the current branch with the same name on the remote.

    If you are working on a centralized workflow (pushing to the same repository you pull from, which is typically origin), then you need to configure an upstream branch with the same name.

    This mode is the default since Git 2.0, and is the safest option suited for beginners.

  • matching - push all branches having the same name on both ends. This makes the repository you are pushing to remember the set of branches that will be pushed out (e.g. if you always push maint and master there and no other branches, the repository you push to will have these two branches, and your local maint and master will be pushed there).

    To use this mode effectively, you have to make sure all the branches you would push out are ready to be pushed out before running git push, as the whole point of this mode is to allow you to push all of the branches in one go. If you usually finish work on only one branch and push out the result, while other branches are unfinished, this mode is not for you. Also this mode is not suitable for pushing into a shared central repository, as other people may add new branches there, or update the tip of existing branches outside your control.

    This used to be the default, but not since Git 2.0 (simple is the new default).

https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushdefault

remote.pushDefault

The remote to push to by default. Overrides branch.<name>.remote for all branches, and is overridden by branch.<name>.pushRemote for specific branches.

https://git-scm.com/docs/git-config#Documentation/git-config.txt-remotepushDefault

branch.<name>.pushRemote

When on branch <name>, it overrides branch.<name>.remote for pushing. It also overrides remote.pushDefault for pushing from branch <name>. When you pull from one place (e.g. your upstream) and push to another place (e.g. your own publishing repository), you would want to set remote.pushDefault to specify the remote to push to for all branches, and use this option to override it for a specific branch.

https://git-scm.com/docs/git-config#Documentation/git-config.txt-branchltnamegtpushRemote

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 to origin.

When the command line does not specify what to push with <refspec>... arguments or --all, --mirror, --tags options, the command finds the default <refspec> by consulting remote.*.push configuration, and if it is not found, honors push.default configuration to decide what to push (See git-config[1] for the meaning of push.default).

When neither the command-line nor the configuration specifies what to push, the default behavior is used, which corresponds to the simple value for push.default: the current branch is pushed to the corresponding upstream branch, but as a safety measure, the push is aborted if the upstream branch does not have the same name as the local one.

https://git-scm.com/docs/git-push#_description

git push

Works like git push <remote>, where <remote> is the current branch’s remote (or origin, 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 the push.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 for git push origin.

https://git-scm.com/docs/git-push#_examples

nothing.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, origin2/ba, origin3/ba)

@test "fails when no <repository>" {
    start_cloned_repo
    git config push.default nothing
    git commit --allow-empty -m B

    run git push

    assert_equal "$status" 128
    assert_output "fatal: You didn't specify any refspecs to push, and push.default is \"nothing\"."
}

@test "fails when no <refspec>" {
    start_cloned_repo
    git config push.default nothing
    git commit --allow-empty -m B

    run git push origin

    assert_equal "$status" 128
    assert_output "fatal: You didn't specify any refspecs to push, and push.default is \"nothing\"."
}

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() {
    (mk_bare_repos)
    cd "$BATS_TEST_TMPDIR"
    git clone a.git b
    cd b
    git config user.email [email protected]
    git config user.name "Your Name"
    git remote add origin2 ../a2.git
    git fetch origin2
    git remote add origin3 ../a3.git
    git fetch origin3
}

mk_bare_repos() {
    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)

    mv a/.git a.git
    (cd a.git
    git config core.bare true)

    cp -r a.git a2.git
    cp -r a.git a3.git
}

ml() { for l; do printf '%s\n' "$l"; done; }

upstream.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, origin2/ba, origin3/ba)

@test "pushes to the matching upstream branch" {
    start_cloned_repo
    git config push.default upstream
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin/ba ba
}

@test "pushes to the non-matching upstream branch" {
    start_cloned_repo
    git config push.default upstream
    git push origin ba:bb; git branch -u origin/bb
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin/bb ba
}

@test "pushes to the non-origin upstream branch" {
    start_cloned_repo
    git config push.default upstream
    git branch -u origin2/ba
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin2/ba ba
}

@test "pushes to the local upstream branch" {
    start_cloned_repo
    git config push.default upstream
    git branch bb; git branch -u bb
    git commit --allow-empty -m B

    git push

    assert_equal_sha bb ba
}

@test "fails when no upstream branch" {
    start_cloned_repo
    git config push.default upstream
    git branch --unset-upstream
    git commit --allow-empty -m B

    run git push

    assert_equal "$status" 128
    assert_output -p 'fatal: The current branch ba has no upstream branch.'
}

@test "remote.pushDefault can't override the target remote" {
    start_cloned_repo
    git config push.default upstream
    git config remote.pushDefault origin2
    git commit --allow-empty -m B

    run git push

    assert_equal "$status" 128
    assert_output -p "`ml \
        "fatal: You are pushing to remote 'origin2', which is not the upstream of" \
        "your current branch 'ba', without telling me what to push" \
        "to update which remote branch."`"
}

@test "branch.<name>.pushRemote can't override the target remote" {
    start_cloned_repo
    git config push.default upstream
    git config branch.ba.pushRemote origin2
    git commit --allow-empty -m B

    run git push

    assert_equal "$status" 128
    assert_output -p "`ml \
        "fatal: You are pushing to remote 'origin2', which is not the upstream of" \
        "your current branch 'ba', without telling me what to push" \
        "to update which remote branch."`"
}

@test "<repository> can't override the target remote" {
    start_cloned_repo
    git config push.default upstream
    git commit --allow-empty -m B

    run git push origin2

    assert_equal "$status" 128
    assert_output -p "`ml \
        "fatal: You are pushing to remote 'origin2', which is not the upstream of" \
        "your current branch 'ba', without telling me what to push" \
        "to update which remote branch."`"
}

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() {
    (mk_bare_repos)
    cd "$BATS_TEST_TMPDIR"
    git clone a.git b
    cd b
    git config user.email [email protected]
    git config user.name "Your Name"
    git remote add origin2 ../a2.git
    git fetch origin2
    git remote add origin3 ../a3.git
    git fetch origin3
}

mk_bare_repos() {
    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)

    mv a/.git a.git
    (cd a.git
    git config core.bare true)

    cp -r a.git a2.git
    cp -r a.git a3.git
}

ml() { for l; do printf '%s\n' "$l"; done; }

simple.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, origin2/ba, origin3/ba)

@test "pushes to the matching upstream branch" {
    start_cloned_repo
    git config push.default simple
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin/ba ba
}

@test "pushes to the matching non-origin upstream branch" {
    start_cloned_repo
    git config push.default simple
    git branch -u origin2/ba
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin2/ba ba
}

@test "fails when no upstream branch" {
    start_cloned_repo
    git config push.default simple
    git branch --unset-upstream
    git commit --allow-empty -m B

    run git push

    assert_equal "$status" 128
    assert_output -p 'fatal: The current branch ba has no upstream branch.'
}

@test "fails when the branch names don't match" {
    start_cloned_repo
    git config push.default simple
    git push origin ba:bb; git branch -u origin/bb
    git commit --allow-empty -m B

    run git push

    assert_equal "$status" 128
    assert_output -p "`ml \
        'fatal: The upstream branch of your current branch does not match' \
        'the name of your current branch.'`"
}

@test "remote.pushDefault overrides the target remote" {
    start_cloned_repo
    git config push.default simple
    git config remote.pushDefault origin2
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin2/ba ba
}

@test "branch.<name>.pushRemote overrides remote.pushDefault" {
    start_cloned_repo
    git config push.default simple
    git config remote.pushDefault origin
    git config branch.ba.pushRemote origin2
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin2/ba ba
}

@test "<repository> overrides branch.<name>.pushRemote" {
    start_cloned_repo
    git config push.default simple
    git config branch.ba.pushRemote origin
    git commit --allow-empty -m B

    git push origin2

    assert_equal_sha origin2/ba ba
}

@test "simple is the default mode" {
    start_cloned_repo
    git push origin ba:bb; git branch -u origin/bb
    git commit --allow-empty -m B

    run git push

    assert_equal "$status" 128
    assert_output -p "`ml \
        'fatal: The upstream branch of your current branch does not match' \
        'the name of your current branch.'`"
}

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() {
    (mk_bare_repos)
    cd "$BATS_TEST_TMPDIR"
    git clone a.git b
    cd b
    git config user.email [email protected]
    git config user.name "Your Name"
    git remote add origin2 ../a2.git
    git fetch origin2
    git remote add origin3 ../a3.git
    git fetch origin3
}

mk_bare_repos() {
    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)

    mv a/.git a.git
    (cd a.git
    git config core.bare true)

    cp -r a.git a2.git
    cp -r a.git a3.git
}

ml() { for l; do printf '%s\n' "$l"; done; }

current.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, origin2/ba, origin3/ba)

@test "pushes to the matching upstream branch" {
    start_cloned_repo
    git config push.default current
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin/ba ba
}

@test "pushes to the matching non-upstream branch" {
    start_cloned_repo
    git config push.default current
    git push origin ba:bb; git branch -u origin/bb
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin/ba ba
}

@test "pushes to the matching non-origin branch" {
    start_cloned_repo
    git config push.default current
    git branch -u origin2/ba
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin2/ba ba
}

@test "doesn't push to a local upstream branch" {
    start_cloned_repo
    git config push.default current
    git branch bb; git branch -u bb
    git commit --allow-empty -m B

    git push

    assert_not_equal_sha bb ba
}

@test "pushes to a non-origin remote when no upstream branch and no other remotes" {
    start_cloned_repo
    git config push.default current
    git commit --allow-empty -m B
    git remote rm origin
    git remote rm origin3

    git push

    assert_equal_sha origin2/ba ba
}

@test "pushes to the origin remote when no upstream branch and more than 1 remote" {
    start_cloned_repo
    git config push.default current
    git branch --unset-upstream
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin/ba ba
}

@test "fails when no upstream branch, more than 1 remote, but the origin remote doesn't exist" {
    start_cloned_repo
    git config push.default current
    git commit --allow-empty -m B
    git remote rm origin

    run git push

    assert_equal "$status" 128
    assert_output -p 'fatal: No configured push destination.'
}

@test "creates the matching branch when not exists" {
    start_cloned_repo
    git config push.default current
    git checkout -b bb

    git push

    assert_branch refs/remotes/origin/bb
}

@test "remote.pushDefault overrides the target remote" {
    start_cloned_repo
    git config push.default current
    git config remote.pushDefault origin2
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin2/ba ba
}

@test "branch.<name>.pushRemote overrides remote.pushDefault" {
    start_cloned_repo
    git config push.default current
    git config remote.pushDefault origin
    git config branch.ba.pushRemote origin2
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin2/ba ba
}

@test "<repository> overrides branch.<name>.pushRemote" {
    start_cloned_repo
    git config push.default current
    git config branch.ba.pushRemote origin
    git commit --allow-empty -m B

    git push origin2

    assert_equal_sha origin2/ba 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() {
    (mk_bare_repos)
    cd "$BATS_TEST_TMPDIR"
    git clone a.git b
    cd b
    git config user.email [email protected]
    git config user.name "Your Name"
    git remote add origin2 ../a2.git
    git fetch origin2
    git remote add origin3 ../a3.git
    git fetch origin3
}

mk_bare_repos() {
    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)

    mv a/.git a.git
    (cd a.git
    git config core.bare true)

    cp -r a.git a2.git
    cp -r a.git a3.git
}

ml() { for l; do printf '%s\n' "$l"; done; }

matching.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, origin2/ba, origin3/ba)

@test "pushes to the matching upstream branch" {
    start_cloned_repo
    git config push.default matching
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin/ba ba
}

@test "pushes to the matching non-upstream branch" {
    start_cloned_repo
    git config push.default matching
    git push origin ba:bb; git branch -u origin/bb
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin/ba ba
}

@test "pushes to the matching non-origin branch" {
    start_cloned_repo
    git config push.default matching
    git branch -u origin2/ba
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin2/ba ba
}

@test "doesn't push to a local upstream branch" {
    start_cloned_repo
    git config push.default matching
    git branch bb; git branch -u bb
    git commit --allow-empty -m B

    git push

    assert_not_equal_sha bb ba
}

@test "pushes to a non-origin remote when no upstream branch and no other remotes" {
    start_cloned_repo
    git config push.default matching
    git commit --allow-empty -m B
    git remote rm origin
    git remote rm origin3

    git push

    assert_equal_sha origin2/ba ba
}

@test "pushes to the origin remote when no upstream branch and more than 1 remote" {
    start_cloned_repo
    git config push.default matching
    git branch --unset-upstream
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin/ba ba
}

@test "fails when no upstream branch, more than 1 remote, but the origin remote doesn't exist" {
    start_cloned_repo
    git config push.default matching
    git commit --allow-empty -m B
    git remote rm origin

    run git push

    assert_equal "$status" 128
    assert_output -p 'fatal: No configured push destination.'
}

@test "doesn't push when the matching branch doesn't exist" {
    start_cloned_repo
    git config push.default matching
    git checkout -b bb

    git push

    refute_branch refs/remotes/origin/bb
}

@test "remote.pushDefault overrides the target remote" {
    start_cloned_repo
    git config push.default matching
    git config remote.pushDefault origin2
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin2/ba ba
}

@test "branch.<name>.pushRemote overrides remote.pushDefault" {
    start_cloned_repo
    git config push.default matching
    git config remote.pushDefault origin
    git config branch.ba.pushRemote origin2
    git commit --allow-empty -m B

    git push

    assert_equal_sha origin2/ba ba
}

@test "<repository> overrides branch.<name>.pushRemote" {
    start_cloned_repo
    git config push.default matching
    git config branch.ba.pushRemote origin
    git commit --allow-empty -m B

    git push origin2

    assert_equal_sha origin2/ba ba
}

@test "pushes other branches when the upstream branch is non-local" {
    start_cloned_repo
    git config push.default matching
    git commit --allow-empty -m B
    git checkout -b bb
    git push origin bb; git branch -u origin/bb

    git push

    assert_equal_sha origin/ba ba
}

@test "doesn't push other branches when the upstream branch is local" {
    start_cloned_repo
    git config push.default matching
    git commit --allow-empty -m B
    git checkout -b bb
    git branch bc; git branch -u bc

    git push

    assert_not_equal_sha origin/ba ba
}

@test "pushes other branches when no upstream branch and only 1 remote" {
    start_cloned_repo
    git config push.default matching
    git commit --allow-empty -m B
    git checkout -b bb
    git remote rm origin
    git remote rm origin3

    git push

    assert_equal_sha origin2/ba ba
}

@test "pushes other branches when no upstream branch and the origin remote exists" {
    start_cloned_repo
    git config push.default matching
    git commit --allow-empty -m B
    git checkout -b bb

    git push

    assert_equal_sha origin/ba 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() {
    (mk_bare_repos)
    cd "$BATS_TEST_TMPDIR"
    git clone a.git b
    cd b
    git config user.email [email protected]
    git config user.name "Your Name"
    git remote add origin2 ../a2.git
    git fetch origin2
    git remote add origin3 ../a3.git
    git fetch origin3
}

mk_bare_repos() {
    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)

    mv a/.git a.git
    (cd a.git
    git config core.bare true)

    cp -r a.git a2.git
    cp -r a.git a3.git
}

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