let's assume we've the following working copy structure:
.
├── adm
└── etc
with
$ git remote -v
origin git@github.com:xxx/my.git (fetch)
origin git@github.com:xxx/my.git (push)
Now, let's assume we've added a sub-project via git subtree
:
git remote add extlip git@github.com:yyy/ExtLib.git
git subtree add -P tech -m "added extlib as a sub-project" extlib/master
Such that
.
├── adm
├── etc
└── tech
with
$ git remote -v
origin git@github.com:xxx/my.git (fetch)
origin git@github.com:xxx/my.git (push)
extlip git@github.com:yyy/ExtLib.git (fetch)
extlip git@github.com:yyy/ExtLib.git (push)
Now assume you aren't working on this project for a while, how do you identify the root of the sub-project? Say, how do you identify the location where you "subtree-ed" and which one is the correct remote? Or, how do you identify that you "subtree-ed" at all?
One way of detecting the commit where a subtree was added is to look for a merge commit where the two parents do not belong to the same tree, or in other words those two commits do not share any previous commit in their history.
An example script of how to detect such in bash running it from the root your git repository:
#!/bin/bash
# To separate the rev-list by newlines
IFS=$'\n'
# This rev list will return the hash and the parents, separated by spaces,
# of any merge commit found in the history of HEAD
for hashes in $(git rev-list --merges --parents HEAD); do
# To split the commits by space
IFS=$' '
hashList=($hashes)
# Merge base will find the most recent commit shared by all the
# given commits, output dumped just to not clutter
git merge-base ${hashList[1]} ${hashList[2]} > /dev/null
# We care only if such commit did not exist, which means each parent is
# in its own separate tree
if [[ $? != 0 ]]; then
echo "Subtree merge: ${hashList[0]}"
fi
done
unset IFS