Search code examples
gitgit-rebase

How do I squash commits in git with a commit date that is not in the past?


So, I have a very simple use case; I want to squash all the commits that need to go back into master from my 'todays working' branch.

Until now I've been using git rebase -i for this, but it doesn't work quite right; the timestamp on the final commit isn't right.

Here's an example of doing this:

[work1] git checkout master
Switched to branch 'master'

[work1] git rebase today
First, rewinding head to replay your work on top of it...
Fast-forwarded master to today.

[work1] git log --pretty=format:"%h%x09%an%x09%ad%x09%s"
5ad95ff Doug    Wed Nov 7 10:12:42 2012 +0800   Updated TODO again
abb891c Doug    Wed Nov 7 10:12:24 2012 +0800   Added more work
c5fd35c Doug    Wed Nov 7 10:11:50 2012 +0800   Added more work
a98facd Doug    Wed Nov 7 10:11:22 2012 +0800   Add work
b4465be Doug    Tue Nov 6 21:38:53 2012 -0800   Updated TODO
403cea9 Doug    Fri Jan 2 21:38:53 2009 -0800   Added todo

Right, now I want to squash these last four commits into one commit.

[work2] date
Wed  7 Nov 2012 10:39:39 WST

[work2] git rebase -i b4465be

pick a98facd Add work
squash c5fd35c Added more work
squash abb891c Added more work
squash 5ad95ff Updated TODO to reflect todays work

And the result:

[work2] git log
commit 3f7f1d2eb4ef23c73dce95f718152c7d5683a926
Author: Doug <[email protected]>
Date:   Wed Nov 7 10:11:22 2012 +0800

    Add work
    Added more work
    Added more work
    Updated TODO to reflect todays work

commit b4465bee5b278214704edcfef3f6e222b5b52964
Author: Doug <[email protected]>
Date:   Tue Nov 6 21:38:53 2012 -0800

    Updated TODO

No! That's not what I wanted. The timestamp of the resulting commit is the timestamp of the commit we squashed into; what I wanted was the new commit date to be the current time.

Just to show exactly what I'm talking about:

[work2] date
Wed  7 Nov 2012 10:39:39 WST

Author: Doug <[email protected]>
Date:   Wed Nov 7 10:11:22 2012 +0800

I want the resulting commit to be date by the merge time, ie. now, not the time of the commit.

As far as I'm aware you can only squash down into a previous commit, not upwards into a new commit, but is there some way of doing this?

The correct solution seems to be

  1. create a new commit with the merge message and the correct commit date time,
  2. ??? <--- somehow squash previous commits into this one.

How do I do that?


Solution

  • Hack: You can use

    git commit --amend --reset-author
    

    The git commit man page says that this "also renews the author timestamp". You don't have to make any changes to the commit (I tried it locally), and it will update the timestamp to the current time. Definitely kind of an abuse, but it seems to work.