Reputation: 15314
In Git, given (1) a branch A and (2) a branch B derived from A at some point in the past and then merged back into A, how can I find all the commits now in A that originated in B?
The intent is to identify the changeset of work performed in B now in A to more quickly track down issues.
A squash commit would obviously and conveniently pack the entire changeset in one commit for easy reference, but the drawbacks (such as loss of information and individual attributability) make this option undesirable for us. Hence my question.
Upvotes: 4
Views: 630
Reputation: 324012
Take a look at git-resurrect.sh script in contrib/
area of git sources.
usage: git resurrect [-a] [-r] [-m] [-t] [-n] [-b <newname>] <name> -b, --branch ... save branch as instead of <name> -a, --all same as -l -r -m -t -k, --keep-going full rev-list scan (instead of first match) -l, --reflog scan reflog for checkouts (enabled by default) -r, --reflog-merges scan for merges recorded in reflog -m, --merges scan for merges into other branches (slow) -t, --merge-targets scan for merges of other branches into -n, --dry-run don't recreate the branch git-resurrect attempts to find traces of a branch tip called <name>, and tries to resurrect it. Currently, the reflog is searched for checkout messages, and with `-r' also merge messages. With `-m' and `-t', the history of all refs is scanned for "Merge <name> into other" / "Merge <other> into <name>" (respectively) in commit subjects, which is rather slow but allows you to resurrect other people's topic branches.
Upvotes: 1
Reputation: 62238
Assuming that B
was fully merged into A
, you can use:
git cherry -v <merge-commit>^ <topic-branch>
...where:
<merge-commit>^
is the parent of the commit where you merged the topic branch.<topic-branch>
is the branch that you want to checkUpvotes: 5
Reputation: 497752
Once a branch has been merged back in, the merge commit is the marker of its existence. Assuming you don't monkey around too much with your merge commit messages, you could do something like this:
#!/bin/bash
die_with_usage() {
# add a git alias for merged-commits to be able to call it like this
echo "usage: git merged-commits <branch-merged> <branch-merged-into>" 1>&2
exit 1
}
if [ $# -ne 2 ]; then
die_with_usage
fi
# Find the merge commits
merges=($(git log --pretty=%H --grep="Merge branch '$1' into $2"))
if [ ${#merges[@]} -eq 0 ]; then
echo "error: no such merges found!" 1>&2
die_with_usage
fi
for merge in ${merges[@]}; do
# The first parent is the merged-into branch
bar=$merge^1
# The second is the merged branch
foo=$merge^2
# Find the merge base
base=$(git merge-base $bar $foo)
# Show the commits
git log --pretty=%H $base..$foo
done
I figured it'd be helpful to just print the SHA1s and let you go off and do what you like with them afterward, but of course you can fiddle with the output format of that last git log
.
(And I even tested this! Might keep it around; it's a cool little few-liner.)
Another thing you can do (in the future) is adopt a merge commit message along the lines of git.git, which essentially embeds the shortlog of the merged commits in the merged commit message (here's an example). There's a built-in way to do this coming someday (it's been merged to next but not master) but for now you'd have to roll your own, or make a gutsy move and build from next.
Upvotes: 1