Skip to content

Instantly share code, notes, and snippets.

@x-yuri
Last active December 24, 2024 14:03
Show Gist options
  • Save x-yuri/7b7e05cdfffc7001fff6cfeb712128f2 to your computer and use it in GitHub Desktop.
Save x-yuri/7b7e05cdfffc7001fff6cfeb712128f2 to your computer and use it in GitHub Desktop.
git: FETCH_HEAD

git: FETCH_HEAD

the Stack Overflow answer

git fetch writes the references it fetches to .git/FETCH_HEAD (one per line). If the upstream branch is set, the corresponding reference is marked for merging. FETCH_HEAD is the reference (i.e. the remote-tracking branch) marked for merging if the upstream branch is set, or the first reference in .git/FETCH_HEAD otherwise.

Basically after git fetch (or git pull) FETCH_HEAD points to the tip of the upstream branch, that you want to merge or rebase onto.

The relevant docs:

The names of refs that are fetched, together with the object names they point at, are written to .git/FETCH_HEAD. This information may be used by scripts or other git commands, such as git-pull[1].

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

it tells git fetch the default refspec to be marked for merging in FETCH_HEAD

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

FETCH_HEAD

records the branch which you fetched from a remote repository with your last git fetch invocation.

https://git-scm.com/docs/git-rev-parse#Documentation/git-rev-parse.txt-codeFETCHHEADcode

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 ba)
# a (origin/ba) --- b (HEAD -> bb, origin/bb)

@test ".git/FETCH_HEAD contains all the fetched refs" {
    start_cloned_repo

    git fetch

    assert_equal "`cut -f1 .git/FETCH_HEAD | sort`" \
        "`
            git show-ref \
                | awk '{p = "^refs/remotes/origin/"} $2 ~ p' \
                | grep -Fv '/HEAD' \
                | cut -f1 -d' ' \
                | sort
        `"
}

@test "first comes the ref that corresponds to the upstream branch" {
    start_cloned_repo

    git fetch

    assert_equal "`head -1 .git/FETCH_HEAD | cut -f1`" \
                 "`git rev-parse bb`"
}

@test "the first ref is marked for merging if the upstream branch is set" {
    start_cloned_repo

    git fetch

    assert_equal "`cut -f2 .git/FETCH_HEAD`" \
                 $'\nnot-for-merge'
}

@test "no refs are marked for merging if no upstream branch is set" {
    start_cloned_repo
    git branch --unset-upstream

    git fetch

    assert_equal "`cut -f2 .git/FETCH_HEAD`" \
                 $'not-for-merge\nnot-for-merge'
}

@test "FETCH_HEAD is the first ref in .git/FETCH_HEAD if the upstream branch is set" {
    start_cloned_repo

    git fetch

    assert_equal "`git rev-parse FETCH_HEAD`" \
                 "`head -1 .git/FETCH_HEAD | cut -f1`"
}

@test "FETCH_HEAD is the first ref in .git/FETCH_HEAD if no upstream branch is set" {
    start_cloned_repo
    git branch --unset-upstream

    git fetch

    assert_equal "`git rev-parse FETCH_HEAD`" \
                 "`head -1 .git/FETCH_HEAD | cut -f1`"
}

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 branch -m ba
    git config user.email [email protected]
    git config user.name "Your Name"
    git commit --allow-empty -m a
    git checkout -b bb
    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 .
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment