3

I recently forked, committed, and made a pull request to a public repository where I am not a collaborator. My pull request hasn't been merged yet.

Looking through my commits, I realized I committed using the wrong author name and I want to fix it. I tried doing a rebase, which works great:

git rebase -i HEAD~7

Then I edited all the commits in question and, based on this answer, successfully changed the author of the commits.

git commit --amend --author "James <email@example.com>" --no-edit && \
git rebase --continue

Everything is good so far, but I noticed this changes the commit times to the current time. I want to preserve the previous timestamps. I tried following this answer, but filter-branch appears to have changed the hashes for the entire repository.

I probably shouldn't force push this. And even if I did, it probably would make it so that my pull request couldn't be merged. So, I tried looking for a way to run filter-branch on the last few commits on the branch, but I couldn't find anything. I tried:

git filter-branch --env-filter 'GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; export GIT_COMMITTER_DATE' HEAD~7

But that doesn't work. It exits with the error message:

Which ref do you want to rewrite?

What should I try to do? Is this possible?

Should I look into the --committer-date-is-author-date flag for the rebase? What does that do?

Community
  • 1
  • 1
James Taylor
  • 6,158
  • 8
  • 48
  • 74

2 Answers2

2

Just pass the range of revisions you want to git filter-branch, like this:

git filter-branch --env-filter 'GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; export GIT_COMMITTER_DATE' HEAD~7..HEAD
Matthieu Moy
  • 15,151
  • 5
  • 38
  • 65
1

I wouldn't worry about it. Observe that although the commit date changes, the author date is preserved.

If you think about it, this makes sense, given git's semantics: whenever the commit SHA changes, it's a new commit, and the commit-date should change, too.


However, the following should work:

$ git rebase --committer-date-is-author-date --onto origin/master master my-feature-branch

The above command will take all of the commits on my-feature-branch which are not in master, and rebase them atop origin/master. Because of the provided --committer-date-is-author-date, the author date will be duplicated to the commit date, but only if you do not use -i or --interactive.

This should still work even though you've rewritten your local history, although I haven't tried this.


Concerning the rebase command:

Here is the general form:

$ git rebase --onto NEW_BASE OLD_BASE SOME_BRANCH

If SOME_BRANCH is a branch from OLD_BASE, this will take all of the commits between OLD_BASE and SOME_BRANCH, and apply them to NEW_BASE instead of OLD_BASE.

Here is a more specific command, based on the few refs you provided:

$ git rebase --committer-date-is-author-date --onto origin/master HEAD~7 my-feature-branch
jpaugh
  • 6,634
  • 4
  • 38
  • 90
  • The flag `--committer-date-is-author-date` didn't really work like I thought it would. Do you know if `filter-branch` can be run on the last few commits? – James Taylor May 24 '15 at 02:18
  • According to the docs, `--committer-date-is-author-date` does what you want. However, it is incompatible with the `--interactive` option to `git rebase`. Did you try it without specifying `--interactive`? – jpaugh May 24 '15 at 02:21
  • No, I haven't. I'll try that now. – James Taylor May 24 '15 at 02:23
  • I actually have no idea how to do a non-interactive rebase. Can you please provide more sample code in your answer? I'd really appreciate it. Thank you! – James Taylor May 24 '15 at 02:34
  • If you know how to rebase interactively, then you know how to rebase non-interactively. Just leave off the `-i` switch. If you're worried about munging your branch, you can always use a new branch, or do `git reset my-feature-branch@{1}` to undo the rebase afterward. – jpaugh May 24 '15 at 02:55
  • Note: I've updated the code sample, and made another. You rarely have to explicitly specify all three refs for a rebase, but if you do, you can be guaranteed that it will grab only the commits that you want. – jpaugh May 24 '15 at 02:57
  • Thank you so much for the extra example! One quick question: what happens once I start the rebase? I want to call `commit --amend` on each of them. Right now I get the message: `First, rewinding head to replay your work on top of it` Again, thank you for your help! – James Taylor May 24 '15 at 03:11
  • If you really want to preserve commit dates **and** rebase interactively (e.g. to edit each commit), then you'll need to rebase twice. Do it once the usual way (with `-i`), and then again as I showed above. – jpaugh May 27 '15 at 02:20