Home > database >  How can I prevent amending a commit when in the middle of a merge conflict?
How can I prevent amending a commit when in the middle of a merge conflict?

Time:07-04

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.

  •  Tags:  
  • git
  • Related