My git repository has three branches, devel
, stable
and customers/acme_patches
. A long time ago, stable
was forked from <
Not sure if it covers all cases, but here's the functions that I came up with:
git_branch_contains() {
local b=$1
local c=$2
IFS_=$IFS
IFS=$'\n'
local branches=($(git branch --contains "$c" | sed -E 's/^(\*| ) //'))
IFS=$IFS_
for b2 in "${branches[@]:+${branches[@]}}"; do
if [ "$b2" = "$b" ]; then
return 0
fi
done
return 1
}
git_upstream_branch() {
local b=$1
local c1=$(git merge-base --fork-point master "$b") || local c1=
local c2=$(git merge-base --fork-point dev "$b") || local c2=
if ! [ "$c1" ]; then
echo dev
return
fi
if ! [ "$c2" ]; then
echo master
return
fi
local fp
if git merge-base --is-ancestor "$c1" "$c2"; then
fp=$c2
else
fp=$c1
fi
if git_branch_contains master "$fp" && ! git_branch_contains dev "$fp"; then
echo master
else
echo dev
fi
}
And here's the script to test them (git-upstream-branch-test.sh
):
#!/usr/bin/env bash
set -eu
. git-upstream-branch.sh
git_commit() {
if ! [ "${commit_i:-}" ]; then
commit_i=0
fi
(( commit_i++ )) || true
echo "$commit_i" > "$commit_i"
git add "$commit_i"
git commit -qm "c$commit_i"
}
git_merge() {
if ! [ "${merge_i:-}" ]; then
merge_i=0
fi
(( merge_i++ )) || true
git merge -m "$merge_i" $1
}
A_TOPOLOGY=${1:-}
mkdir git-upstream-branch-test-repo
cd git-upstream-branch-test-repo
git init -q
if [ "$A_TOPOLOGY" = 10 ]; then
git_commit
git_commit
git checkout -qb dev
git_commit
git_commit
git checkout -q master
git_commit
git_commit
c=$(git rev-parse HEAD)
git_commit
git_commit
git checkout -q dev
git checkout -qb t1
git_commit
git_commit
git checkout -q dev
git_commit
git_commit
git rebase --onto "$c" dev t1
elif [ "$A_TOPOLOGY" = 11 ]; then
git_commit
git_commit
git checkout -qb dev
git_commit
git_commit
git checkout -q master
git_commit
git_commit
git checkout -q dev
c=$(git rev-parse HEAD)
git_commit
git_commit
git checkout -q master
git checkout -qb t1
git_commit
git_commit
git checkout -q master
git_commit
git_commit
git rebase --onto "$c" master t1
else
git_commit
git_commit
git checkout -qb dev
git_commit
git_commit
git checkout -q master
git_commit
git_commit
if [ "$A_TOPOLOGY" = 4 ] || [ "$A_TOPOLOGY" = 5 ] || [ "$A_TOPOLOGY" = 6 ]; then
git_merge dev
git_commit
git_commit
git checkout -q dev
git_commit
git_commit
git checkout -q master
elif [ "$A_TOPOLOGY" = 7 ] || [ "$A_TOPOLOGY" = 8 ] || [ "$A_TOPOLOGY" = 9 ]; then
git checkout -q dev
git_merge master
git_commit
git_commit
git checkout -q master
git_commit
git_commit
fi
git checkout -qb t1
git_commit
git_commit
git checkout -q master
git_commit
git_commit
if [ "$A_TOPOLOGY" = 2 ] || [ "$A_TOPOLOGY" = 5 ] || [ "$A_TOPOLOGY" = 8 ]; then
git_merge dev
elif [ "$A_TOPOLOGY" = 3 ] || [ "$A_TOPOLOGY" = 6 ] || [ "$A_TOPOLOGY" = 9 ]; then
git checkout -q dev
git_merge master
fi
fi
git --no-pager log --oneline --graph --decorate --all
git_upstream_branch t1
Use it like so,
$ rm -rf git-upstream-branch-test-repo && ./git-upstream-branch-test.sh NUMBER
Where NUMBER is a number from 1 to 11 to specify which case (topology) to test.