Andrew Grimm
Andrew Grimm

Reputation: 81450

Do a git reset only if other branches refer to the commits

Is there any way to remove a couple of commits from a branch only if a different branch refers to the commits?

For example, if I did the following commits:

ABC-1: Add views for feature ABC-1
ABC-1: Add controller action for feature ABC-1

and then I discovered that I did them on the develop branch, rather than on feature/ABC-1, I'd do

git checkout -b feature/ABC-1
git checkout develop
git reset --hard HEAD~~

is there any options I can pass to git reset that'll refuse to do the git reset if I hadn't created the feature/ABC-1 branch? Kind of like how git branch -d only deletes a branch if it refers to commits that are included in the branch you're currently on?

I could do

git checkout -b feature/ABC-1
git branch -d develop
git checkout HEAD~~
git checkout -b develop

but that loses information about which remote branch develop is tracking.

Upvotes: 0

Views: 31

Answers (1)

torek
torek

Reputation: 487755

There is nothing built in to git reset, but git branch --contains <commit-specifier> shows every branch whose tip commit has the specified commit as part of its history. Hence, if you are on a branch at all, git branch --contains HEAD will print one name if you are on a branch whose tip commit is not contained in any other branch, or two or more names if you are on a branch whose tip commit is contained in some other branches. (And you get no names at all if you are on a detached HEAD pointing to a commit not contained in any branch, or one name if you are on a detached HEAD contained in one branch.)

Parsing the output of git branch is slightly fragile since it's a porcelain command rather than a plumbing command. A sufficiently new version of Git has flags in git for-each-ref that provide robust handling for scripts. In this case, however, git branch --contains HEAD | wc -l is solid enough. Hence (untested and written more for illustrative purposes than anything else):

#! /bin/sh
# make sure we are in a git directory at all
git rev-parse -q --verify HEAD >/dev/null || exit
# are we on any (named) branch? if so, which one?
if current_branch=$(git symbolic-ref -q HEAD 2>/dev/null); then
    detached=false
    expected=1
else
    detached=true
    expected=0
fi
count=$(git branch --contains HEAD | wc -l)
extra=$((count - expected))
if [ $extra -gt 0 ]; then
    echo "other branch(es) protect the HEAD commit"
else
    echo "moving HEAD would lose commits"
fi

Upvotes: 1

Related Questions