Basically I want something similar to git branch -a --no-merged
but I'd also like to list tags and I don't need the spaces before or stuff like remotes/origin/HEAD -> origin/master
Can I do this with for-each-ref or is it better to just strip the stuff I don't want from git branch
then get the tags separately?
You can use the git merge-base command to find the latest common commit between the two branches. If that commit is the same as your branch head, then the branch has been completely merged.
The more the branches and master diverge away from each other the farther away their “common ancestor” commit becomes. When you're done with a branch and it has been merged into master, delete it. A new branch can be made off of the most recent commit on the master branch.
Suppose you are on branch master and you want to check if the git merge origin/devel will work. Then just do: git merge-tree `git merge-base origin/devel master` master origin/devel .
Actually, starting with the upcoming git 2.7 (Q4 2015), git for-each-ref
, will support the --no-merged
option, allowing for an easy filter of the merged branches
git for-each-ref --no-merged master refs/heads/
With the doc:
--no-merged [<object>]:
Only list refs whose tips are not reachable from the specified commit (HEAD if not specified).
See commit 4a71109, commit ee2bd06, commit f266c91, commit 9d306b5, commit 7c32834, commit 35257aa, commit 5afcb90, ..., commit b2172fd (07 Jul 2015), and commit af83baf (09 Jul 2015) by Karthik Nayak (KarthikNayak
).
(Merged by Junio C Hamano -- gitster
-- in commit 9958dd8, 05 Oct 2015)
Some features from "
git tag -l
" and "git branch -l
" have been made available to "git for-each-ref
" so that eventually the unified implementation can be shared across all three, in a follow-up series or two.
* kn/for-each-tag-branch:
for-each-ref: add '--contains' option
ref-filter: implement '--contains' option
parse-options.h: add macros for '--contains' option
parse-option: rename parse_opt_with_commit()
for-each-ref: add '--merged' and '--no-merged' options
ref-filter: implement '--merged' and '--no-merged' options
ref-filter: add parse_opt_merge_filter()
for-each-ref: add '--points-at' option
ref-filter: implement '--points-at' option
user3265569 proposes in the comments:
I've added some formatting using your suggestion.
git for-each-ref --no-merged master \ --format='%(committerdate:relative),%(authorname),%(refname:short)' \ --sort=committerdate \ | column -t -s ','
git for-each-ref
and the similar git show-ref
do not have the ability to decide whether one reference is an ancestor of another on its own, but you can always build a pipeline, e.g.:
uninteresting=master # or some other way to identify ones to discard
git for-each-ref |
while read sha1 reftype refname; do
if git merge-base --is-ancestor $refname $uninteresting; then
# $refname / $sha1 "is merged", or is exactly equal
... do whatever you like here ...
else
# there is no ancestry path from $uninteresting back to $refname
... do whatever else you like here ...
fi
done
Note that git merge-base --is-ancestor master master
is always true. If you don't want "equal but name differs" considered to be "merged" (and does this depend on whether it's a branch or some other ref type?) you will need some extra code here, but I suspect you do want "equal means merged".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With