Git is an interesting version control system, one that enables workflows not possible with earlier version control systems. However, there are days I wish it was less… Powerful? Cryptic? Unfathomable? Irritating? (Too far?)

I'm not entirely sure how it happened, but I recently realized my local master repository had somehow gotten ahead of origin/master, the authoritative version of a repository. (I'm sure I did something without realizing it.)

Now, I don't work in master. Usually, I create individual branches and submit pull requests (PRs) when a work item is complete. Each PR is reviewed and approved before being merged. (At least, that's the workflow for this particular project.)

I noticed new pull requests for my individual branches included commits from other branches, generally branches associated with PRs still under review. Unfortunately, I've been busy this week and checked in quite a few pull requests before noticing the problem.

Ideally, each branch contains just the commits appropriate for the underlying work item. I needed to update each problematic PR branch.

Here's what I did:

  1. For each affected pull request, create a new pull request containing just the intended commit.
  2. Once all affected branches have been replaced, reset master to origin/master to avoid on-going problems.

Resetting and replacing pull requests

You can't simply remove commits from a pull request. Instead, create a new branch, reset it to origin/master, and then cherry-pick the commit(s) you want the branch to track.

Here's how it works:

  1. Determine (and save) the ID for the commit you want to keep:

     $ git checkout broken-branch 
     $ git log

    In my case, the commit ID was the first commit in each log. Your needs likely vary.

  2. Create and checkout a new branch.

     $ git checkout -b broken-branch-upd

    Tip: I base the new name on the old branch name (ex: broken-branch-upd) for continuity. I also leave relevant comments on each PR explaining the situation while pointing to the other PR. This creates an audit trail in case someone down the line wonders what the heck I was doing.

  3. Reset the new branch to origin/master.

     $ git fetch origin master
     $ git reset --hard origin/master

    If you receive a Fatal: could not read from remote repository error while trying fetch origin master, it's likely one of the following:

    • You've mistyped origin; verify that the remote origin is specified correctly.
    • The current working directory isn't part of origin/master. In this case, change to an appropriate directory and try again.
  4. Cherry-pick the desired commit(s) from the original pull request.

     $ git cherry-pick saved-commit-id
  5. Review and verify your local files. When satisfied, push your changes to Github:

     $ git push origin broken-branch-upd:broken-branch-upd
  6. At this point, you can create a new pull request (which should be blissfully free from other commits) and delete the original one. Don't forget to delete the branches.

If you're planning to add additional commits to the new PR, push a small edit to one of the files in scope of the PR. This may trigger the upstream warning that appears when local branches aren't tracked remotely. If the warning appears, use the prompt text to track your local branch.

$ git push --set-upstream origin broken-branch-upd

Do so now to avoid future surprises and head-scratching.

Resetting and replacing pull requests

Once the PRs are all straightened out, you'll want to resolve the differences between your local master and origin.

First, check out master, investigate the differences, and resolve them. (I was lucky; each difference was a commit represented in a different PR.)

Once you've accounted for the differences, reset master to origin:

$ git checkout master
$ git fetch origin master
$ git reset --hard origin/master
$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean

Now, you're ready to return to your regularly developed workflow.

Vital statistics

Last tested: 8 March 2017 using git 2.10.1, MacOS Sierra 10.12.3

Source: Derived from Stack Overflow Q# 25955822. My mileage varied, so I wrote this up and added my commentary.