Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare old and new versions of force-pushed GitHub pull request

Frequently, my colleagues will make some changes to an open pull request, rebase their local branch against the base branch - often squashing their changes into previous commits as well - and force-push.

How can I see what changed between the old version of the PR and the new version of the PR?

I guess I could do a git pull and git checkout $BRANCH_NAME when the PR was first raised, then git fetch and then git diff $BRANCH_NAME..origin/$BRANCH_NAME after the PR was updated - but that will also show changes that have been introduced into the base branch (typically master) and brought into the PR via a rebase. Is it possible to remove that noise and just show what has changed in the PR itself?

like image 362
Robin Green Avatar asked Sep 25 '16 08:09

Robin Green


People also ask

How do I compare pull requests on GitHub?

Submitting pull request on GitHubNavigate to the original GitHub repository, and you should see a big green button marked "Compare and pull request". Click that button and you will be taken to a page giving you the opportunity to describe your pull request and showing you the changes you have made.

What is the difference between pushing and pulling in GitHub?

Push: sends commits and asks them to update their branch. This requires that things be right on their end. This cannot combine parallel development. Pull: runs git fetch , which gets commits and has your Git update your remote-tracking name, then runs a second Git command to update your branch.

Should I make a new branch for each pull request?

It's a good practice to create a new branch for every new bit of work you start doing, even if it's a very small one. It's especially useful to create a new branch for every new feature you start working on. Branches are of course disposable, you can always remove them.

Which two branches are compared in the pull request?

Pull requests display diffs to compare the changes you made in your topic branch against the base branch that you want to merge your changes into. Note: When creating your pull request, you can change the base branch that you're comparing your changes against. For more information, see "Creating a pull request."


2 Answers

the old version of the PR

You can do so directly on GitHub: see "Find committer of a force push on GitHub"

Clicking the “force-pushed” link will show a two dot comparison between the two commits.


Original answer: 2016

That would be only available in the reflog of the remote repo, which would include the previous HEAD of the branch force-pushed.
Since the remote repo is a GitHub one, you still can infer the old commit by looking at push events: see "Does github remember commit IDs?".

hat will also show changes that have been introduced into the base branch (typically master)

More exactly, you will always have the differences against a common ancestor (which will include commits from the base branch like master)

See What are the differences between double-dot ".." and triple-dot "..." in Git diff commit ranges?

http://mythic-beasts.com/~mark/git-diff-help.png

So in your case, your forced-pushed branch looks like this on the remote repo:

      x--x--x        (old branch in reflog)      /  m--M0--M--M   (master)             \              X--X--X (new branch forced push) 

A diff old_HEAD..newHEAD would include the few M commits from the base branch, as they are part of the common ancestor (M0) path.

So you can compare a force-pushed branch (providing you are monitoring pushEvents and know of the previous HEAD of that branch).
But uou cannot easily compare two branches without their common ancestor path.

like image 50
VonC Avatar answered Sep 24 '22 09:09

VonC


Checkout this answer to another question which want to do something very similar to what you are trying to achieve.

It describe your situation like this:

newcommit -> the new pull request commit oldcommit -> the old pull request commit upstream -> the base branch commit the new pull request is based on 

Now do this:

git commit-tree newcommit^{tree} -p oldcommit -p upstream -m "message" git show <commit id returned by previous command> 

The idea is that commit-tree will fake a merge between oldcommit and upstream producing newcommit tree and thus containing exactly the code of newcommit. It does not modify your current branch at all, it create a new headless commit and give you its ID. This means git show will list every modification as a conflict resolution, which is the exact difference between the new PR and the old one.

To be able to do that you need to have the previous PR in your git repository somewhere (if a force push has been performed the git history has been rewritten and can't be recovered unless you have it on your pc or you have access to the server reflog). Check VonC answer for details about this.

Assuming:

  • base branch: master
  • you have locally the old PR branch: $BRANCH_NAME
  • the new PR in a remote branch: origin/$BRANCH_NAME

You can do like this:

# fetch locally upstream changes (origin/$BRANCH_NAME) git fetch # produce the fake merge commit git commit-tree origin/$BRANCH_NAME^{tree} \          -p $BRANCH_NAME \          -p `git merge-base master origin/$BRANCH_NAME` \          -m "message" # see "fake" conflict resolution = difference between the two PR git show <commit id returned by previous command> 

the git merge-base is used to find the common ancestor between two branches, in this case to find the commit on which the new PR is based on in the base branch, if you prefer you can write the commit ID directly.

like image 38
Daniele Segato Avatar answered Sep 23 '22 09:09

Daniele Segato