Change timezone for all commits in git history

1.7k views Asked by At

I'm converting an old CVS repository to git, which has worked very well except all the commits are in UTC instead of each author's local timezone.

I would like to change the timezone of these commits on a per-author basis, so for example all commits from one author change from +0000 to +1000, while commits from other authors are unchanged. (So I can perform this procedure once for each author.)

The actual moment in time should stay the same, so a commit that is currently 02:00:00 +0000 should become 12:00:00 +1000.

Is this possible with something like git filter-branch?

2

There are 2 answers

1
Malvineous On BEST ANSWER

I've come up with this, which seems to do the trick:

git filter-branch --env-filter '
    if [ "$GIT_AUTHOR_EMAIL" == "[email protected]" ]; then
        export GIT_AUTHOR_DATE=`echo $GIT_AUTHOR_DATE | sed s/+0000/+1000/`
    fi
    if [ "$GIT_COMMITTER_EMAIL" == "[email protected]" ]; then
        export GIT_COMMITTER_DATE=`echo $GIT_COMMITTER_DATE | sed s/+0000/+1000/`
    fi'

This changes the timezone for author [email protected] from +0000 to +1000. If the timezone is already something else in a given commit then it will be left unchanged. In the event that this person was the author but not the committer (or vice-versa), only the date for their role will be updated.

It won't handle changing UTC offsets due to DST as @MattJohnson pointed out, but perhaps you can add additional criteria for that if needed.

This works by taking advantage of git's internal date format, which is always measured in seconds since the epoch and looks like @12345 +0000. The timezone here is not used (the number of seconds is always in UTC) which allows you to alter the timezone without changing the effective moment in time that is being referenced. Changing the UTC offset here only affects the default formatting of the date.

1
Thomas Jacob On

In addition to @Malvineous' answer:

If it's okay to use the current user's timezone as a reference, you can use Git to do the DST conversion. This did the trick for me, fixing all commits' timezones to the current timezone, including DST change.

git filter-branch --env-filter '
  if [ "$GIT_AUTHOR_EMAIL" == "[email protected]" ]; then
    GIT_AUTHOR_DATE=`echo $GIT_AUTHOR_DATE|sed -e "s/[+-][0-9]\{4\}//g"`
  fi
  if [ "$GIT_COMMITTER_EMAIL" == "[email protected]" ]; then
    GIT_COMMITTER_DATE=`echo $GIT_COMMITTER_DATE|sed -e "s/[+-][0-9]\{4\}//g"`
  fi
'

The sed line strips off the timezone. GIt takes care of the rest.

Please note that this does not support an explicit timezone as initially requested, but takes care of DST.

NOTE: The original answer had an additional lines using date, e.g.,

GIT_AUTHOR_DATE=`date --date=$GIT_AUTHOR_DATE`

However, this is not necessary because handles uses the current timezone (including DST) when none is specified. Therefore, chopping the timezone is sufficient.