Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to filter out merged branches in git for-each-ref?

Tags:

git

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?

like image 628
Monte Goulding Avatar asked Dec 06 '13 05:12

Monte Goulding


People also ask

How can you see all branches with merged work?

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.

Do merged branches get deleted?

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.

How can you tell if two branches are merged?

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 .


2 Answers

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 ','
like image 199
VonC Avatar answered Oct 13 '22 19:10

VonC


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".

like image 43
torek Avatar answered Oct 13 '22 19:10

torek