My workflow usually involves uploading commits for review e.g. commit chain A(HEAD) -> B -> C - and if I get a review on commit B - I run git rebase -i, select B for editing, and then run git commit --amend followed by git rebase --continue to patch the commit with fixes in-place in the chain.
This is the common flow, but sometimes - when I edit B I get a merge conflict in A.
The way an interactive rebase workflow is supposed to work is that I resolve the conflicts, stage them with git add - and then run git rebase --continue without amending the commit.
However, the merge-conflict-free git commit --amend flow is so common that I often find myself making the absentminded mistake of running git commit --amend; git rebase --continue instead of git rebase --continue - which wreaks havoc on my chain, squashing two commits together and I then need to delve into git reflog to unsquash them.
This is almost never the desired behavior, and is usually a mistake - it's rare that someone would want to amend a new commit with resolved merge conflicts into the previous commit.
Is there a way to configure git to disallow amending a commit when in the middle of a merge conflict?
CodePudding user response:
During rebase, there is a .git/rebase-merge directory. --amend can be captured in the hook prepare-commit-msg.
or commit, followed by a commit object name (if a -c, -C or --amend option was given).
So one of the ideas is to fail prepare-commit-msg and abort the commit if .git/rebase-merge exists and --amend is used. In order to bypass the test, we can define a config value, foo.bar.
A demo in Bash,
#!/bin/bash
msg_file=$1
msg_source=$2
msg_object=$3
foo_bar=$(git config --get foo.bar)
if [[ "${foo_bar}" != "false" ]];then
gitdir=$(git rev-parse --absolute-git-dir)
rebase_dir=${gitdir}/rebase-merge
if [[ -d "${rebase_dir}" ]] && [[ "$msg_source" = commit ]];then
echo "Forbid 'git commit --amend' during rebase"
echo "Maybe you want 'git rebase --continue'?"
echo "If you do want to amend during rebase, use 'git -c foo.bar=false commit --amend'"
exit 1
fi
fi
The side effect is that git commit -C $commit or git commit -c $commit during rebase are also failed. But we can bypass it with -c foo.bar=false.
