How can I write a commit hook to cherry-pick last commit from main branch to other worktrees in a bare repo?

92 views Asked by At

I have 3 branches called main, macos and linux. As soon as I commit something to main branch, I want to cherry-pick that commit to other two branches. I also want to do this in a bare repo.

❯ git clone --bare <bare-repo-url>
❯ cd my-bare-repo
❯ git worktree add main
❯ git worktree add linux
❯ git worktree add macos
❯ cd main
❯ touch README.md
❯ git add README.md
❯ git commit -m "Add README" # <- this commit should be cherry picked to the other two branches

Actually, if I write the following 2 commands in shell, I can manually do that:

❯ git --git-dir=<path-to-bare-repo>/worktrees/linux --work-tree=<path-to-bare-repo>/linux cherry-pick main
❯ git --git-dir=<path-to-bare-repo>/worktrees/macos --work-tree=<path-to-bare-repo>/macos cherry-pick main

But when I write a post-commit hook for this job, somehow it doesn't work as expected. It is working like as if I didn't provided --git-dir and --work-tree options and try to cherry-pick from the same branch and conflict happens. How can I fix this script?

#!/bin/bash
current_branch=$(git symbolic-ref --short HEAD)

# Check if committing to the main branch
if [ "$current_branch" = "main" ]; then
    gitdir=$(dirname `pwd`)
    # Update the linux branch
    git --git-dir="$gitdir/worktrees/linux" --work-tree="$gitdir/linux" cherry-pick main

    # Update the macos branch
    git --git-dir="$gitdir/worktrees/macos" --work-tree="$gitdir/macos" cherry-pick main

fi
❯ git commit -m "Add README"
error: your local changes would be overwritten by cherry-pick.
hint: commit your changes or stash them to proceed.
fatal: cherry-pick failed
error: your local changes would be overwritten by cherry-pick.
hint: commit your changes or stash them to proceed.
fatal: cherry-pick failed
[main ed96ee9] Add README
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README

I also tried cd ../linux; git cherry-pick main but it didn't work too.

1

There are 1 answers

0
sahinakkaya On

I found the answer. The problem is fixed after adding unset GIT_INDEX_FILE to the script.

...
gitdir=$(dirname `pwd`)
unset GIT_INDEX_FILE
...

Quoting the original answer directly:

The problem here is that in post-commit hooks (and also pre-commit, prepare-commit-msg and commit-msgt) the GIT_INDEX_FILE environment variable is set to .git/index. (This isn't documented in the githooks documentation, but I've posted elsewhere about the settings of environment variables and the current directory in git hooks.)

The effect of the GIT_INDEX_FILE environment variable is described in the ENVIRONMENT VARIABLES section of the git man page as:

GIT_INDEX_FILE

This environment [variable] allows the specification of an alternate index file. If not specified, the default of $GIT_DIR/index is used.

... and for some reason, in this situation, GIT_INDEX_FILE is being used relative to GIT_WORK_TREE.

To make the hook work as you would expect, you just need to unset GIT_INDEX_FILE, so your hook would look like:

 #!/bin/sh
 unset GIT_INDEX_FILE
 export GIT_WORK_TREE=/var/www/example/
 export GIT_DIR=/home/mark/test/.git/
 git checkout -f