commit: warn when a new commit is dated before its parent
PATCH 1/1 commit: warn when a new commit is dated before its parent
From: Devi Srinivas Vasamsetti <[email protected]>
Git writes whatever the clock says into the commit object. This can be problematic because history traversal assumes commit dates are non-decreasing. For example, "git log --since" stops walking at the first commit older than the cutoff, so an out-of-order date hides the commits behind it.
Add a check gated by a new advice.clockSkew setting that warns when the new commit's date precedes a parent's date. This allows users to catch a wrong clock at commit time when it is still easy to fix.
This check only looks at the new commit being created and its parents. Dates in replayed history or merges are not warned about.
---
commit: warn when a new commit is dated before its parent
What does this PR do? This PR adds a helpful warning if you try to make a new commit with a date that is older than its parent commit.
Why is this needed? Git just uses whatever time your computer's clock says when creating a commit. If your system clock is incorrect, you might accidentally create a commit dated in the past.
This causes problems because commands like git log --since assume that commit dates always move forward. If a date goes backward in history, those commands can get confused and accidentally hide commits from the log.
What is fixed? We added a new configuration setting called advice.clockSkew. Now, Git will warn you right away if your computer's clock seems to be wrong when you are making a new commit. This gives you a chance to fix your computer's time before you accidentally push out-of-order dates!
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2235%2Fsrinivas1591%2Ffeature%2Fwarn-older-commits-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2235/srinivas1591/feature/warn-older-commits-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/2235
Documentation/config/advice.adoc | 7 +++++ advice.c | 1 + advice.h | 1 + builtin/commit.c | 46 ++++++++++++++++++++++++++++++++ t/t7502-commit-porcelain.sh | 27 +++++++++++++++++++ 5 files changed, 82 insertions(+)
Documentation/config/advice.adoc +7 -0
@@ -38,6 +38,13 @@ all advice messages. configuration variable for how to set a given remote to be used by default in some situations where this advice would be printed. + clockSkew:: + Shown by linkgit:git-commit[1] when the commit being + created is dated earlier than one of its parents, which + usually means the system clock is wrong. History + traversal assumes commit dates do not decrease, so such + a commit can cause commands like `git log --since` to + skip the commits behind it. commitBeforeMerge:: Shown when linkgit:git-merge[1] refuses to merge to avoid overwriting local changes.
advice.c +1 -0
@@ -50,6 +50,7 @@ static struct { [ADVICE_AMBIGUOUS_FETCH_REFSPEC] = { "ambiguousFetchRefspec" }, [ADVICE_AM_WORK_DIR] = { "amWorkDir" }, [ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME] = { "checkoutAmbiguousRemoteBranchName" }, + [ADVICE_CLOCK_SKEW] = { "clockSkew" }, [ADVICE_COMMIT_BEFORE_MERGE] = { "commitBeforeMerge" }, [ADVICE_DEFAULT_BRANCH_NAME] = { "defaultBranchName" }, [ADVICE_DETACHED_HEAD] = { "detachedHead" },
advice.h +1 -0
@@ -17,6 +17,7 @@ enum advice_type {ADVICE_AMBIGUOUS_FETCH_REFSPEC ,ADVICE_AM_WORK_DIR ,ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME , +ADVICE_CLOCK_SKEW ,ADVICE_COMMIT_BEFORE_MERGE ,ADVICE_DEFAULT_BRANCH_NAME ,/* To be retired sometime after Git 3.0 */ ADVICE_DETACHED_HEAD,
builtin/commit.c +46 -0
70 lines not on this page · raw message
t/t7502-commit-porcelain.sh +27 -0
@@ -1003,4 +1003,31 @@ test_expect_success WITH_BREAKING_CHANGES 'core.commentChar=auto is rejected' ' test_cmp expect actual ' +test_expect_success 'warn when a commit is dated before its parent' ' + test_when_finished "git checkout main 2>/dev/null || git checkout master" && + git checkout -b clock-skew && + test_commit --date "2026-09-25T10:00:00+0000" skew-parent && + echo skew >skew-child && + git add skew-child && + GIT_COMMITTER_DATE="2026-09-13T06:00:00+0000" \ + git commit -m "behind its parent" 2>actual && + test_grep "earlier than its parent" actual +' + +test_expect_success 'no warning when commit dates increase' ' + echo forward >skew-forward && + git add skew-forward && + GIT_COMMITTER_DATE="2026-09-26T06:00:00+0000" \ + git commit -m "after its parent" 2>actual && + test_grep ! "earlier than its parent" actual +' + +test_expect_success 'advice.clockSkew silences the warning' ' + echo quiet >skew-quiet && + git add skew-quiet && + GIT_COMMITTER_DATE="2026-09-14T06:00:00+0000" \ + git -c advice.clockSkew=false commit -m quiet 2>actual && + test_grep ! "earlier than its parent" actual +' + test_done
base-commit: 3bc0341126508f78f5869cbfc0005e987efdf0c7
Signature · 1 line
gitgitgadget
"Devi Srinivas Vasamsetti via GitGitGadget" <[email protected]>
Quoted 7 lines · writes:
From: Devi Srinivas Vasamsetti <[email protected]>
Git writes whatever the clock says into the commit object. This can be problematic because history traversal assumes commit dates are non-decreasing. For example, "git log --since" stops walking at the first commit older than the cutoff, so an out-of-order date hides the commits behind it.
It might be annoying, but the value of such a warning is unclear. If you clone from an upstream repository, you might find that the commit at the tip was made on a machine with a clock set far in the future. When you try to make a commit on top of it, what are you supposed to do? Wait for a year so your commit is newer than the tip? Ask the committer to correct their clock, redo the commit, and force-push?
It also does not help if the commit at the tip of the cloned branch has a timestamp in the past, but is a child of a commit with an incorrect timestamp. Nobody would receive a warning, yet --since may still stop prematurely.
Stepping back a bit, suppose you clone from upstream and obtain a HEAD dated 24 hours ago, HEAD~1 dated 72 hours ago, and HEAD~2 dated 48 hours ago. A command like git log --since=50.hours may stop without showing HEAD~2, but if you suspect that some clocks are skewed, there is no way to determine the correct output from these timestamps anyway. It is possible that HEAD~1 has an incorrect timestamp and was actually written 30 hours ago, meaning all three commits should be shown. Alternatively, HEAD~2 might have an incorrect timestamp and was written 80 hours ago, in which case showing neither HEAD~1 nor HEAD~2 is correct.
The moral of the story is that --since or any other time-based option cannot be fully reliable, as you cannot force everyone to run with a correctly synchronized clock. If you truly need to know the ancestral relationship between commits, you should avoid these options and use topology-based ones instead.