87

Is it possible to change the commit date from my commit to the author date?

I adapted some commits and now the dates are all the same. I want to set it back to the old dates (or the author dates). Is this possible?

I am using Sourcetree so I have the git command line but I am not a pro at that. My external repository is bitbucket.

kevingoos
  • 3,785
  • 4
  • 36
  • 63

4 Answers4

128

Short Answer:

git filter-branch --env-filter 'export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"'

Explanation:

filter-branch lets you rewrite your git history. It can apply transformations to each commit or filter out commits based on certain criteria. See git filter-branch --help for a comprehensive description and usage instructions.

--env-filter allows you to set the environment variables that are present during the creation of the new history. It is evaluated for each commit separately.

jsphpl
  • 4,800
  • 3
  • 24
  • 27
  • 4
    A little explanation would be great. – starikcetin May 21 '18 at 02:12
  • 1
    @S.TarıkÇetin this command simply sets `committer-date=author-date` as requested by kevingoos – anion Jan 21 '19 at 15:19
  • 4
    We can also define commit range at the end `git filter-branch -f --env-filter '...' 338f1ac1..HEAD`. – Orkhan Alikhanov Dec 24 '20 at 11:38
  • To do it on the most recent commit (the head), use `HEAD^..HEAD` as the commit range. Also, for the options, adding `-f/--force` may sometimes be necessary (for example you still have a backup from last run). – ADTC Jul 21 '22 at 18:39
88

Since git 1.6.3 git rebase has --committer-date-is-author-date for this purpose.

git rebase --committer-date-is-author-date

Original answer:
There's no easy way to set the committer dates (edit: but see "edit 2" below). The author dates are easy to adjust (at commit time) since --date will let you specify each one as you go.

The environment variable GIT_COMMITTER_DATE can be used to force a different time stamp at the time you make the commit. Note, however, that you'd need to adjust this for each commit you "replay". The resulting new commit will have a different SHA-1 (because you've changed some bits in it, namely, the committer date field), which means you must redo all its descendent commits.

This is what git filter-branch does (re-create some, many, or all commits with changes made along the way, keeping a mapping from old SHA-1 IDs to new SHA-1 IDs and adjusting the parents of even-otherwise-untouched commit copies so that the "new" DAG of new SHA-1 IDs matches the "old" DAG in every possible way, i.e., in every way except for SHA-1 IDs and any other changes made by your filter(s)).

In other words, to do this, you must use git filter-branch to rewrite history, with all that this implies. [Edit: you can literally do it without git filter-branch, e.g., by doing it in git rebase -i instead, but the effect is the same.]

Edit 2: as eis noted in a comment (since removed), git rebase has --committer-date-is-author-date for this purpose. It still does the same history rewriting, but it's a lot more convenient than doing it with the raw git filter-branch command.

audun
  • 134
  • 1
  • 7
torek
  • 448,244
  • 59
  • 642
  • 775
  • 6
    `--committer-date-is-author-date` seems to be quite broken when combined with `--root`, unfortunately. – user1338062 Aug 20 '18 at 07:15
  • 6
    Notice that we can use e.g., `git rebase --committer-date-is-author-date HEAD~3` to only apply it to the most three recent commits. – He Yifei 何一非 Aug 02 '20 at 11:13
  • @HeYifei何一非 Yes—but only if those three commits are ordinary single-parent commits; watch out for merges in your history. The `HEAD~3` notation counts back three first-parents. – torek Aug 02 '20 at 16:27
  • True, but I had put a `break` in the middle of a `rebase -i` and I couldn't do _another_ rebase with the existing rebase in progress. `filter-branch` was the only way in this unique scenario. – ADTC Jul 21 '22 at 18:40
5

I wanted to piggyback on the answer from jsphpl because I was looking for a way to do this, but with two differences:

  • I only wanted to change the commits in my current branch
  • I wanted the rewritten commits to be signed

First you will need the ID of the first commit in your branch:

git log master..your-branch-name --pretty="%H" | tail -1

The output of that will look something like this: c04b195ca1ed4c8a18c6a98d67b8a764a3006afc

Take that ID and plug it into the command below:

git filter-branch -f \
--env-filter 'export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"' \
--commit-filter 'git commit-tree -S "$@";' \
c04b195ca1ed4c8a18c6a98d67b8a764a3006afc^...your-branch-name

The commit date and author date of each commit should now match. You can double check by running the command below to easily view and compare the commit date values:

git log --format="%H %cI %aI %s" master...your-branch-name
David DeMar
  • 2,390
  • 2
  • 32
  • 45
5

One-liner with filter-repo:

You can also use filter-repo (a recommended replacement for filter-branch) like this:

git filter-repo --commit-callback 'commit.committer_date = commit.author_date'

This is significantly more performant than filter-branch.

Arad Alvand
  • 8,607
  • 10
  • 51
  • 71
  • 1
    Be aware that some Git commands can get greatly confused and misbehave if the committer timestamps are not monotonically increasing. This can happen after this command if applied to a history where commits have been rearranged with `git rebase`. – j6t Nov 04 '22 at 10:58
  • @j6t Thanks for pointing that out; though it's not specific to my answer; this applies to the accepted answer as well. – Arad Alvand Nov 04 '22 at 11:48