Skip to content
Browse files

Add topic-base and topic-merge

  • Loading branch information...
1 parent 3f5bbbe commit 86e0e36380f43aab4c845d17290399aa610e0ea3 @ConradIrwin ConradIrwin committed
Showing with 118 additions and 0 deletions.
  1. +11 −0 README.markdown
  2. +67 −0 bin/git-topic-base
  3. +40 −0 bin/git-topic-merge
View
11 README.markdown
@@ -54,6 +54,17 @@ This is mostly for use in aliases: some of `git reset`'s behaviour is too
verbose to type often, but too dangerous to be easy to type, so this gives you
something that's safe to alias to something short.
+## git-topic-merge ##
+If you have a pointer to the last commit on a topic branch, topic-merge will
+find the merge commit that integrated that topic branch into an integration
+branch.
+
+## git-topic-base ##
+If you have a pointer to the last commit on a topic branch, topic-base will
+find the commit on which the branch was based. This is not the merge base in
+the case that you have merged the topic into the integration branch before.
+(for limitations, see `git-topic-base -h`)
+
## git-uncommit ##
Removes the previous commit, without changing the working tree. Can accept
filenames to remove the changes to those files from the previous commit, or -p
View
67 bin/git-topic-base
@@ -0,0 +1,67 @@
+#!/bin/bash -e
+if [ "$(echo "$@" | grep '\(--help\|-h\)')" ]
+then
+ cat <<'HEREDOC'
+git topic-base <integration-branch> [<topic>=HEAD]
+
+Find the base node on the <integration-branch> from which the <topic> diverged.
+This differs from the merge base if you've merged an earlier version of the
+topic into the integration branch.
+
+Graphically, this tool works on the following shape of history:
+
+ B-----O---O---M--- (integration)
+ \ / / /
+ `-T"--T'--T (topic)
+
+ M: The merge that most recently merged topic with integration,
+ note that T is a direct parent of M.
+ O: Other merges of T into I, you can have as many of these as you like.
+ R: The base commit that this finds.
+ T: The HEAD of the topic branch just before it was merged.
+
+In particular, this won't work if you use fast-forward merging, nor if you have
+*ever* merged <integration> into <topic>.
+
+Once you have <base>, you can use it to generate a list of commits on the branch:
+
+ git log <topic> --not <base>
+
+or, when combined with topic-merge, pretty graphs:
+
+ git log --graph --oneline $(git topic-merge <topic>) --not <base>^@
+
+You can also use it to rebase the topic onto a master branch:
+
+ git checkout <topic>
+ git rebase --onto <master> <base>
+
+See also: git topic-merge
+
+HEREDOC
+ exit 1
+fi
+integration=${1?Usage: git topic-base [-h] <integration> [<topic>=HEAD]}
+topic=${2:-HEAD}
+
+merge=$(git topic-merge "$integration" "$topic")
+
+# TODO: This should be fixable, M is just the oldest commit in <integration>
+# that contains <topic>.
+[ "$merge" ] || (
+ echo "This only works on commits that have been merged directly into $integration, see git topic-base -h"
+ exit 1
+)
+
+# This works by assuming the graph shown above. Once we've found T, we can find
+# T' by finding M (by just scanning the log of <integration> until we find a
+# merge which included our commit as the non-first olive), and then finding the
+# merge-base of the two parents of M.
+# TODO: Try to catch edge cases!
+while [ $merge ]
+do
+ topic=$(git merge-base "$merge^" "$topic")
+ merge=$(git topic-merge "$integration" "$topic")
+done
+
+echo $topic
View
40 bin/git-topic-merge
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+if [ "$(echo "$@" | grep '\(--help\|-h\)')" ]
+then
+ cat <<'HEREDOC'
+git topic-merge <integration-branch> [<topic>=HEAD]
+
+Find the commit where the <topic> was merged into the
+<integration-branch>.
+
+TODO: At the moment this only works if <topic> is the last commit on the <topic>
+branch.
+
+i.e. you must have a structure like:
+
+ o-o-M-o-I
+ /
+ o-T
+
+ T: The HEAD of the topic branch just before it was merged.
+ I: The HEAD of the integration branch.
+ M: The merge that most recently merged topic with integration,
+
+If T has been directly merged into I several times, the oldest such merge will
+be found:
+
+ o-o-M-o-M'-I
+ / /
+ o-T----
+
+See also: git-topic-base
+
+HEREDOC
+ exit 1
+fi
+
+integration=$(git rev-parse "${1?Usage: git topic-merge [-h] <integration> [<topic>]}")
+topic=$(git rev-parse "${2:-HEAD}")
+
+echo $(git rev-list --parents $integration | grep "[a-f0-9]\+ [a-f0-9]\+ $topic" | tail -n 1 | cut -d' ' -f 1)

0 comments on commit 86e0e36

Please sign in to comment.
Something went wrong with that request. Please try again.