How to fix the order of commits in GitHub Pull Requests
Tags: git, github
Published: 2020-03-29 19:01:02

---
title: How to fix the order of commits in GitHub Pull Requests
published: true
date: 2020-03-10 10:00:00 UTC
tags: Git,GitHub
canonical_url: https://andrewlock.net/how-to-fix-the-order-of-commits-in-github-pull-requests/
---

 ![How to fix the order of commits in GitHub Pull Requests](https://andrewlock.net/content/images/2020/git_rebase_04.png)

In this post I show how to ensure your commits in a GitHub pull request (PR) are in the order you expect for reviewers - i.e. the logical order of the commits to a branch, not the date order.

> Warning: this post uses [rebasing](https://www.atlassian.com/git/tutorials/rewriting-history/git-rebase) to rewrite the history of a Git branch. You should only ever do that to a branch if you're sure other users aren't basing their own work on it!

## The setup: cleaning up a local branch using rebasing

Let's imagine you're working on a feature in a branch, and you've made several commits. In the image below, we have a branch called `test` based off the master branch that has 3 commits:

- `"Commit 1"` is the first commit
- `"Commit 2"` is the second commit
- `"Commit 3"` is the \*drum roll\* third commit

![Image of the Test branch containing three commits](https://andrewlock.net/content/images/2020/git_rebase_00.png)

At this point you've just about finished the feature, but to make things easier for your colleagues, you decide to clean-up your local branch before creating a Pull Request.

Looking at your commits, you decide that it makes sense for `"Commit 3"` to be the first one on the branch, coming before the others.

> Likely you would do extra work here, like squashing some commits, splitting others etc. into something that makes a logical story. The example here of rearranging commits is just the simplest case. Of course, if you squash everything into a single commit, then this whole post is moot!

You can easily rearrange commits using interactive rebase by running

```bash
git rebase origin/master -i
```

This pops up an editor listing the current commits on the branch, and lets you rearrange, edit or squash them for example

```bash
pick 68f39b8 commit 1
pick d605e5a commit 2
pick f3b9e40 commit 3

# Rebase 82df143..d605e5a onto 82df143 (3 commands)
```

By rearranging the commits in the file, git will rearrange the commits in the `test` branch. Now it will look the following:

- `"Commit 3"` is now the first commit
- `"Commit 1"` is the second commit
- `"Commit 2"` is the third commit

![Image of the Test branch containing rearranged commits](https://andrewlock.net/content/images/2020/git_rebase_01.png)

An important point here is that while rearranging the commits changes the git history, the _date_ associated with the commit doesn't change (on the right hand side of the image above). We'll come back to that later…

With the branch all cleaned up, it's time to push your work to the server. You push the branch to GitHub, and create [a pull request](https://github.com/andrewlock/blog-examples/pull/61) for viewing by your colleagues.

> I like to create pull request from the command line using [the `hub` command line tool](https://github.com/github/hub). I wrote about [`hub` in a previous post](https://andrewlock.net/creating-github-pull-requests-from-the-command-line-with-hub/).

Everything probably looks OK initially, but if you look a little closer, there's something not quite right…

## The problem: GitHub doesn't preserve commit order

The problem is that the order of commits shown in the Pull Request do not reflect the actual order of the commits in the branch:

![Image of a Pull Request on GitHub showing commits](https://andrewlock.net/content/images/2020/git_rebase_02.png)

The image above shows the original commit order of 1, 2, 3 instead of the revised order of 3, 1, 2. That's not very helpful, given that we specifically reordered the commits in the branch to make more sense to reviewers who are reviewing commits in sequence.

> Not that GitHub displays commit in **ascending** order of date, whereas [the gitk tool](https://riptutorial.com/git/example/18336/gitk-and-git-gui) I used in the first two screenshot display commits in **descending** order of the branch.

This is [a known issue in GitHub, with a page dedicated to it on their help pages](https://help.github.com/en/github/committing-changes-to-your-project/why-are-my-commits-in-the-wrong-order). Unfortunately, their solution isn't entirely useful:

> "If you always want to see commits in order, we recommend not using `git rebase`."

As someone who uses rebasing as a standard part of their workflow, that's not very helpful.

The problem is that GitHub orders the commits shown in the pull request by the **author** date, not by their logical position in the branch. If you think back to the image of our branch prior to pushing, you'll remember the dates on the commits didn't change when we rebased. That's what GitHub uses, and is the root of the problem.

> It's worth mentioning that there are actually two dates associated with each commit: the **author** date, and the **committer** date. GitHub uses the **author** date to control ordering, which is not changed when you reorder commits using rebasing.

After spending a while rebasing a branch recently, only to have GitHub randomly scatter the commits in the PR, I went looking for a solution.

## The solution: changing the dates on commits

The only solution I could come up with was to rewrite the commit dates to be in the same order as the commits. I looked for a few automated ways of doing this [using `git filter-branch` and similar](https://eddmann.com/posts/changing-the-timestamp-of-a-previous-git-commit/) that I won't show here. The main problem I had was that these were _too_ fast. The commits all ended up having the _same_ date. That made things even worse in the pull request - now the commits were ordered completely randomly!

Instead, I opted for a slightly more manual approach. The approach I took was:

- Interactively rebase the branch
- Mark each commit as requiring editing
- For each commit, edit the commit date to be the current time

In 30 seconds, a moderately sized branch can be updated to ensure all the commit dates match their position in the branch.

The first command is

```bash
git rebase origin/master -i
```

This starts an interactive rebase as before. For each commit in the editor that pops up, change `pick` to `edit` (before the SHA1 hash and title of the commit):

```bash
edit f3b9e40 commit 3
edit 68f39b8 commit 1
edit d605e5a commit 2

# Rebase 82df143..d605e5a onto 82df143 (3 commands)
```

> Multi-cursor editing can really speed up this process - I use VS code as my git editor, which has [built-in support for multi-cursor editing](https://code.visualstudio.com/docs/editor/codebasics#_multiple-selections-multicursor).

When you close the editor, git will start the rebase process. It will apply a single commit, and then wait, allowing you to make any changes. Rather than change any files, run the command below, which updates the dates on the commit without changing anything else:

```bash
git commit --amend --no-edit --date=now
```

Next, run the following command to move to the next one:

```bash
git rebase --continue

```

Keep running those two commands until the rebase is complete. At this point you're all done, and your commit dates should be in ascending order, nicely matching the commit order in the branch:

![Image of the commits on the Test branch with updated dates to match their position on the branch](https://andrewlock.net/content/images/2020/git_rebase_03.png)

If you push this branch to the server and create a pull-request (I used `--force-with-lease` to push over the top of the original branch) then the commits in the pull request will now have the same order as the commits in your local branch:

![Image of the commits in the pull request matching the real commit order](https://andrewlock.net/content/images/2020/git_rebase_04.png)

So the final question is: should you actually do this? As someone who frequently heavily rebases branches before creating a PR, I will. But I absolutely wouldn't recommend rebasing a branch like this if other people are (or might be) basing work of your commits. Changing the commit dates changes the SHA hash of the commit, and can be a good way to make yourself very unpopular with your colleagues!

## Summary

In this post I discussed the problem that GitHub pull requests don't show commits in the order they are found in a branch. Instead, it shows them ordered by author date. If you have rebased your branch, it's possible you will have rearranged some commits, and edited others, so that the author date no longer reflects the logical order of commits. This can sometimes be confusing for reviewers, if they're viewing commits one-by-one.

To fix the problem, I restored to brute-force. I edited each commit in the branch and updated the time. By stepping through and editing each commit after performing all other rebasing, the date order now matches the logical commit order of the branch so the GitHub pull request commit order will now match the logical commit order too!