No, it's not. In fact, it's the exact opposite. From the docs of git rebase : "These flags are passed to git am to easily change the dates of the rebased commits".
To modify older or multiple commits, you can use git rebase to combine a sequence of commits into a new base commit. In standard mode, git rebase allows you to literally rewrite history — automatically applying commits in your current working branch to the passed branch head.
Rebasing can be dangerous! Rewriting history of shared branches is prone to team work breakage. This can be mitigated by doing the rebase/squash on a copy of the feature branch, but rebase carries the implication that competence and carefulness must be employed.
Git will return you to your branch's state as it was before git rebase was called. You can run git rebase --skip to completely skip the commit. That means that none of the changes introduced by the problematic commit will be included. It is very rare that you would choose this option.
Update June 2014: David Fraser mentions in the comments a solution also detailed in "Change timestamps while rebasing git branch", using the option --committer-date-is-author-date
(introduced initially in Jan. 2009 in commit 3f01ad6
Note that the
--committer-date-is-author-date
option seems to leave the author timestamp, and set the committer timestamp to be the same as the original author timestamp, which is what the OP Olivier Verdier wanted.I found the last commit with the correct date and did:
git rebase --committer-date-is-author-date SHA
See git am
:
--committer-date-is-author-date
By default the command records the date from the e-mail message as the commit author date, and uses the time of commit creation as the committer date.
This allows the user to lie about the committer date by using the same value as the author date.
Note: with Git 2.29 (Q4 2020), git rebase --committer-date-is-author-date
or --ignore-date
will also work with:
rebase -i
/rebase --interactive
)git rebase --root
)See "Change timestamps while rebasing git branch".
(Original answer, June 2012)
You could try, for a non-interactive rebase
(see just above: with Git 2.29, Q4 2020, that will work with an interactive rebase as well)
git rebase --ignore-date
(from this SO answer)
This is passed to git am
, which mentions:
--ignore-date
By default the command records the date from the e-mail message as the commit author date, and uses the time of commit creation as the committer date.
This allows the user to lie about the author date by using the same value as the committer date.
For git rebase
, this option is "Incompatible with the --interactive option."
Since you can change at will the timestamp of old commit date (with git filter-branch
), I suppose you can organize your Git history with whatever commit date order you want/need, even set it to the future!.
As Olivier mentions in his question, the author date is never changed by a rebase;
From the Pro Git Book:
- The author is the person who originally wrote the work,
- whereas the committer is the person who last applied the work.
So, if you send in a patch to a project and one of the core members applies the patch, both of you get credit.
To be extra clear, in this instance, as Olivier comments:
the
--ignore-date
does the opposite of what I was trying to achieve!
Namely, it erases the author's timestamp and replace them with the commits timestamps!
So the right answer to my question is:
Do not do anything, sincegit rebase
does actually not change authors' timestamps by default.
As DylanYoung adds in the comments, using "How to identify conflicting commits by hash during git rebase?":
Using the
SEQUENCE_EDITOR
variable and rebase interactive, you would just loop over the currenttodo
list and add a command setting theGIT_COMMITER_DATE
to the date of the original commit before each commit in thetodo
.It's a bit less fiddly because you have the list of original commits to start with (you don't have to hack into git internals to find it), but a bit more work because you have to handle the entire list at once. –
Once you're able to identify the original commit you can do something like:
git rebase -x 'GIT_COMMITTER_DATE="git show -s --format=%ci ``get_current_commit``" git commit --amend --no-edit
If you've already screwed up the commit dates (perhaps with a rebase) and want to reset them to their corresponding author dates, you can run:
git filter-branch --env-filter 'GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; export GIT_COMMITTER_DATE'
A crucial question of Von C helped me understand what is going on: when your rebase, the committer's timestamp changes, but not the author's timestamp, which suddenly all makes sense. So my question was actually not precise enough.
The answer is that rebase actually doesn't change the author's timestamps (you don't need to do anything for that), which suits me perfectly.
By default, git rebase will set the committer's timestamp to the time when the new commit is created, but keep the author's timestamp intact. Most of time, this is the desired behavior, but at some scenarios, we dot not wish to change the commiter's timestamp either. How can we accomplish that? Well, here is the trick I usually do.
First, make sure each of the commits you are about to rebase has a unique commit message and author timestamp (This is where is trick needs improvements, currently it suits my needs though).
Before the rebase, record the committer's timestamp, author's timestamp and commit message of all the commits which will be rebased to a file.
#NOTE: BASE is the commit where your rebase begins
git log --pretty='%ct %at %s' BASE..HEAD > hashlog
Then, let the actual rebase take place.
Finally, we replace the current committer's timestamp with the one recorded in the file if the commit message is the same by using git filter-branch
.
git filter-branch --env-filter '__date=$(__log=$(git log -1 --pretty="%at %s" $GIT_COMMIT); grep -m 1 "$__log" ../../hashlog | cut -d" " -f1); test -n "$__date" && export GIT_COMMITTER_DATE=$__date || cat'
If something goes wrong, just checkout git reflog
or all the refs/original/
refs.
Furthormore, you can do the similar thing to the author's timestamp.
For example, if the author's timestamp of some commits are out of order, and without rearrange these commits, we just want the author's timestamp to show in order, then the following commands will help.
git log --pretty='%at %s' COMMIT1..COMMIT2 > hashlog
join -1 1 -2 1 <(cat hashlog | cut -f 1 | sort -nr | awk '{ print NR" "$1 }') <(cat hashlog | awk '{ print NR" "$0 }') | cut -d" " -f2,4- > hashlog_
mv hashlog_ hashlog
git filter-branch --env-filter '__date=$(__log=$(git log -1 --pretty="%s" $GIT_COMMIT); grep -m 1 "$__log" ../../hashlog | cut -d" " -f1); test -n "$__date" && export GIT_AUTHOR_DATE=$__date || cat'
post-rewrite
hook
This hook works for all of git rebase
, git pull --rebase
and git commit --amend
.
.git/hooks/post-rewrite
set -eu
echo post-rewrite
if [ ! "${CIROSANTILLI_GITHOOKS_DISABLE:-0}" = 1 ]; then
declare -a olds
declare -A oldnew
while IFS= read -r line; do
echo "$line"
old="$(echo "$line" | cut -d ' ' -f1)"
new="$(echo "$line" | cut -d ' ' -f2)"
oldnew[$old]="$new"
olds+=("$old")
news+=("$new")
done
git reset --hard "${news[0]}~"
for old in "${olds[@]}"; do
new="${oldnew[$old]}"
git cherry-pick "$new" &>/dev/null
olddate="$(git log --format='%cd' -n 1 "$old")"
CIROSANTILLI_GITHOOKS_DISABLE=1 \
GIT_COMMITTER_DATE="$olddate" \
git commit \
--amend \
--no-edit \
--no-verify \
&>/dev/null \
;
done
echo
fi
GitHub upstream.
Don't forget to:
chmod +x .git/hooks/post-rewrite
This is a good way to do --committer-date-is-author-date
by default on chosen repos, before someone finally patches a config to set it by default.
And it also works with --committer-date-is-author-date
which does not seem to be exposed on git pull --rebase
.
See also:
man githooks
Tested on git 2.19, Ubuntu 18.04.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With