This is hard to do well. In git, a branch is just an auto-advancing pointer to a commit, and a commit can have any number of branch names on it. Consider this case:
your master: y1---y2---y3
/
master: a---b---c---d---e
\
feature: f1---f2---f3---f4
You checked out branch "master" at c
, and committed y1
, y2
, and y3
. Your history thus looks like a b c y1 y2 y3
. Meanwhile master has advanced to d
and e
, but someone created a feature branch and committed f1
through f4
based on c
. Git has no way to determine that your branch came from master
instead of feature
, so at best you will have a choice of branches to merge.
Were you to do this automatically you would have to apply a heuristic about picking the shortest branch, or the longest branch, or the one with the most/least commits, or something else like that. Naturally, since there are so many options, it's not really a good choice for a git
built-in function. However, using git's "plumbing" functions, you can write your own:
#!/bin/bash
# Tries to determine a good merge base from among all local branches.
# Here used, a "good" merge base is the one sharing the most recent commit
# on this branch. This function will exit 1 if no branch is found,
# or exit 2 in a tie.
#
# Untested - use at your own risk.
MAX_SEARCH=20 # only search the last 20 commits on this branch
FOUND=0
LAST_BRANCH=
# iterate through the commits, most recent first
for COMMIT in $(git rev-list --max-count=$MAX_SEARCH HEAD); do
# check every local branch
for BRANCH in $(git for-each-ref --format="%(refname)" refs/heads); do
# look for the commit in that branch's history
if (git rev-list $BRANCH | fgrep -q COMMIT); then
echo $BRANCH
FOUND=$((FOUND + 1))
LAST_BRANCH="$BRANCH"
fi
done
if [ $FOUND -gt 1 ]; then
# more than one choice; exit
exit 2
elif [ $FOUND -eq 1 ]; then
git merge $LAST_BRANCH
exit 0
fi
done
exit 1 # could not find a parent