tomlogic
tomlogic

Reputation: 11694

Finding submodule commits that never got pushed to a public repository

Can someone help me fill in the missing pieces to a script I'm trying to write? I just realized that I have a public repository that contains references to commits in a submodule that I never pushed to origin (the commits were reorganized before pushing). I don't know how many times it's happened, but I'd like to find out and create temporary branches to push to origin.

So, back to the script. I know that I can get a list of commits with changes to my submodule, which I could filter with grep and use cut to get the actual SHA1 tags from my_submodule:

git log -u origin/master -- my_submodule \
    | grep "^\+Subproject" \
    | cut -d" " -f 3

At that point, I had 20 tags and I just used a text editor to make a script to manually tag each one with "tag_00xx". Then I manually reviewed the repository in Git Extensions and deleted any tags for commits that had made it into origin/master, leaving the one tag that had never been pushed.

What should I have done to only create tags for commits that weren't in origin/master? I know that I can do:

git branch -r --contains <commit_sha1>

But that doesn't set an exit code I can use to selectively create new tags. How could I have completed the automation of my task?

Upvotes: 2

Views: 108

Answers (1)

Mark Longair
Mark Longair

Reputation: 467311

I'd probably do this in the following way - first, you can list all the committed submodule versions without the grep and cut by doing:

git rev-list origin/master | while read COMMIT
do
    SUBMODULE_COMMIT=$(git rev-parse $COMMIT:my_submodule 2> /dev/null)
    if [ $? = 0 ]
    then
        echo $SUBMODULE_COMMIT
    fi
done | sort | uniq > committed-submodule-versions

Then, for each of those, you need to change into the submodule and check if it's in origin/master. Probably the simplest way to do that is to grep the output of git branch -r --contains <SUBMODULE-COMMIT>, since then you can use grep's exit code.

For example:

cd my_submodule
while read S
do
    if git rev-parse --verify $S > /dev/null 2> /dev/null
    then
        git branch -r --contains $S 2> /dev/null \
            | grep origin/master > /dev/null \
            || git branch missing-${S:0:8} $S
    else
        echo $S not found in the repository at all
    fi

done < ../committed-submodule-versions

Another point to note is that I'm creating branches for the unpushed commits rather than tags. The reason for this is that git submodule update causes a git fetch, but not a git fetch --tags, which means that tags that don't point at known commits won't be fetched (!).

Upvotes: 1

Related Questions