# grep open pull requests

4 messages from 2017-01-19 to 2017-01-19. Participants: Jack Bates, Jeff King.
Thread: https://gitlist.dev/t/44916

## Jack Bates, 2017-01-19 18:12

Subject: grep open pull requests
Message-ID: <276f6ed9-ff06-a00f-b88a-4d40d55c6d40@nottheoilrig.com>
URL: https://gitlist.dev/e/276f6ed9-ff06-a00f-b88a-4d40d55c6d40%40nottheoilrig.com

```
I have a couple questions around grepping among open pull requests.

First, "git for-each-ref --no-merged": When I run the following,
it lists refs/pull/1112/head, even though #1112 was merged in commit 
ced4da1. I guess this is because the tip of refs/pull/1112/head is 
107fc59, not ced4da1?

This maybe shows my lack of familiarity with Git details,
but superficially the two commits appear identical -- [1] and [2] --
same parent, etc. Nonetheless they have different SHA-1s.
I'm not sure why that is -- I didn't merge the commit --
but regardless, GitHub somehow still connects ced4da1 with #1112.

So my question is, how are they doing that,
and why can't "git for-each-ref --no-merged" likewise
connect ced4da1 with refs/pull/1112/head?

   $ git clone \
   >   --bare \
   >   --config remote.origin.fetch=+refs/pull/*/head:refs/pull/*/head \
   >   https://github.com/apache/trafficserver.git
   $ cd trafficserver.git
   $ git for-each-ref --no-merged


More generally, what I want is to periodically list open pull requests 
that add or modify lines containing the string "memset". So far I have 
the following in a Makefile. Can you recommend any improvements?

.PHONY: all
all: trafficserver.git
	cd trafficserver.git && git fetch
	cd trafficserver.git && git for-each-ref --format '%(refname)' 
refs/pull --no-merged | \
	  while read refname; do \
	    git log -p "master..$$refname" | grep -q '^+.*memset' && echo 
"$$refname"; \
	  done

trafficserver.git:
	git clone \
	  --bare \
	  --config remote.origin.fetch=+refs/pull/*/head:refs/pull/*/head \
	  https://github.com/apache/trafficserver.git


Lastly, a question more about GitHub than Git, but: Given the way GitHub 
is setup, I hope I can get a list of unmerged pull requests from Git 
alone. Can you think of a way to list *open* pull requests,
or is that status only available out of band?

Thanks!


[1] 
https://github.com/apache/trafficserver/commit/107fc59104cce2a4b527f04e7ac86695c98b568c
[2] 
https://github.com/apache/trafficserver/commit/ced4da13279f834c381925f2ecd1649bfb459e8b

```

## Jeff King, 2017-01-19 19:02

Subject: Re: grep open pull requests
Message-ID: <20170119190227.opjisryyqn766tqy@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20170119190227.opjisryyqn766tqy%40sigill.intra.peff.net
In-Reply-To: <276f6ed9-ff06-a00f-b88a-4d40d55c6d40@nottheoilrig.com>

```
On Thu, Jan 19, 2017 at 11:12:03AM -0700, Jack Bates wrote:

> I have a couple questions around grepping among open pull requests.
> 
> First, "git for-each-ref --no-merged": When I run the following,
> it lists refs/pull/1112/head, even though #1112 was merged in commit
> ced4da1. I guess this is because the tip of refs/pull/1112/head is 107fc59,
> not ced4da1?

Right. Git's `--no-merged` is about commit ancestry.

> This maybe shows my lack of familiarity with Git details,
> but superficially the two commits appear identical -- [1] and [2] --
> same parent, etc. Nonetheless they have different SHA-1s.
> I'm not sure why that is -- I didn't merge the commit --
> but regardless, GitHub somehow still connects ced4da1 with #1112.

The commits differ only in the committer timestamp. Try:

  diff -u <(git cat-file commit 107fc5910) \
          <(git cat-file commit ced4da132)

Is it possible that somebody cherry-pick or rebased it? Looking at the
history of apache/trafficserver, I don't see any merges, which implies
to me that the project is using a rebase workflow to merge PRs.

It's much trickier to find from the git topology whether a particular
history contains rebased versions of commits.  You can look at the
--cherry options to "git log", which use patch-ids to try to equate
commits. Something like:

  git for-each-ref --format='%(refname)' 'refs/pull/*/head' |
  while read refname; do
	if test -z "$(git rev-list --right-only --cherry-pick -1 origin...$refname)
	then
		echo "$refname: not merged"
	fi
  done

That's obviously much less efficient than `--no-merged`, but it should
generally work. The exception is if the rebase changed the commit
sufficiently that its patch-id may have changed.

> So my question is, how are they doing that,

I suspect the answer is "somebody clicked the rebase button GitHub"
which simultaneously did the rebase and marked the PR as merged.

> Lastly, a question more about GitHub than Git, but: Given the way GitHub is
> setup, I hope I can get a list of unmerged pull requests from Git alone. Can
> you think of a way to list *open* pull requests,
> or is that status only available out of band?

That information isn't reflected in the git topology. It's in GitHub's
database. You can ask the API:

  https://developer.github.com/v3/

There are libraries to help with that:

  https://developer.github.com/libraries/

I think that's probably the best answer to your "unmerged" question,
too. Ask the API which PRs are unmerged, and then do whatever git-level
analysis you want based on that.

-Peff

```

## Jack Bates, 2017-01-19 22:12

Subject: Re: grep open pull requests
Message-ID: <9f59c0d7-73d3-1b4c-65ca-700d6e1f4f23@nottheoilrig.com>
URL: https://gitlist.dev/e/9f59c0d7-73d3-1b4c-65ca-700d6e1f4f23%40nottheoilrig.com
In-Reply-To: <20170119190227.opjisryyqn766tqy@sigill.intra.peff.net>

```
On 19/01/17 12:02 PM, Jeff King wrote:
> It's much trickier to find from the git topology whether a particular
> history contains rebased versions of commits.  You can look at the
> --cherry options to "git log", which use patch-ids to try to equate
> commits. Something like:
>
>   git for-each-ref --format='%(refname)' 'refs/pull/*/head' |
>   while read refname; do
> 	if test -z "$(git rev-list --right-only --cherry-pick -1 origin...$refname)
> 	then
> 		echo "$refname: not merged"
> 	fi
>   done
>
> That's obviously much less efficient than `--no-merged`, but it should
> generally work. The exception is if the rebase changed the commit
> sufficiently that its patch-id may have changed.

Cool, thanks for all your help! "git log --cherry-pick" works quite 
well. One thing: I expected the following to be equivalent, but found 
that they're not. Is that by accident or design?

   $ git rev-list --cherry-pick --right-only master...refs/pull/1112/head
   $ git rev-list --cherry-pick master..refs/pull/1112/head

> I think that's probably the best answer to your "unmerged" question,
> too. Ask the API which PRs are unmerged, and then do whatever git-level
> analysis you want based on that.

Right, that makes sense. Thanks again!

```

## Jeff King, 2017-01-19 22:24

Subject: Re: grep open pull requests
Message-ID: <20170119222407.7y55did5hft55s27@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20170119222407.7y55did5hft55s27%40sigill.intra.peff.net
In-Reply-To: <9f59c0d7-73d3-1b4c-65ca-700d6e1f4f23@nottheoilrig.com>

```
On Thu, Jan 19, 2017 at 03:12:53PM -0700, Jack Bates wrote:

> Cool, thanks for all your help! "git log --cherry-pick" works quite well.
> One thing: I expected the following to be equivalent, but found that they're
> not. Is that by accident or design?
> 
>   $ git rev-list --cherry-pick --right-only master...refs/pull/1112/head
>   $ git rev-list --cherry-pick master..refs/pull/1112/head

It's by design. The "left" and "right" notions are defined only for a
three-dot symmetric difference.

In the first command you've asked git to look at commits on _both_
master and the PR, down to their merge base. It marks the tips with a
"left" and "right" bit, and then those bits propagate down.

In the second command, you've only asked for the PR commits, and there
is no left/right bit at all. So --cherry-pick is doing nothing, as it
has no "left" commits to compare to.

-Peff

```
