在保留提交时间戳的同时执行git rebase是否有意义?

我相信结果将是新的分支不一定有按时间顺序提交的日期。这在理论上可行吗?(例如使用管道命令;只是好奇)

如果这在理论上是可能的,那么在实践中是否可能使用rebase而不更改时间戳?

例如,假设我有以下树:

master <jun 2010>
  |
  :
  :
  :     oldbranch <feb 1984>
  :     /
oldcommit <jan 1984>

现在,如果我在master上重新创建oldbranch,提交的日期从1984年2月更改为2010年6月。是否有可能改变这种行为,从而不改变提交时间戳?最后,我将得到:

      oldbranch <feb 1984>
      /
 master <jun 2010>
    |
    :

这有意义吗?git中是否允许有历史记录,即旧的提交有最近的提交作为父?


当前回答

如果你已经搞砸了提交日期(可能是用了一个rebase),想要将它们重置为对应的作者日期,你可以运行:

git filter-branch——env-filter 'GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE;出口GIT_COMMITTER_DATE”

其他回答

冯·C的一个关键问题帮助我理解了发生了什么:当你重基时,提交者的时间戳改变了,但作者的时间戳没有改变,这突然之间就说得通了。所以我的问题其实不够精确。

答案是,rebase实际上不会改变作者的时间戳(您不需要为此做任何事情),这非常适合我。

如果你已经搞砸了提交日期(可能是用了一个rebase),想要将它们重置为对应的作者日期,你可以运行:

git filter-branch——env-filter 'GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE;出口GIT_COMMITTER_DATE”

这是我在我的案例中使用的命令:

GIT_AUTHOR_EMAIL=xaionaro@dx.center git rebase --root -x "bash -c 'git commit --amend --reset-author -CHEAD --date=\"\$(git show --format=%ad -s)\"'"

这里git show——format=%ad -s提取当前日期,——date重新执行它。然后rebase——root -x执行bash -c 'git commit——modify——reset-author -CHEAD——date="$(git show——format=%ad -s)"’。

默认情况下,git rebase将把提交者的时间戳设置为 创建新的提交,但保持作者的时间戳不变。大多数时候, 这是我们期望的行为,但在某些情况下,我们不希望改变 提交者的时间戳。我们怎样才能做到呢?这是 我经常做的把戏。

首先,确保您要重基的每个提交都有唯一的 提交消息和作者时间戳(这是需要改进的技巧,目前它适合我的需求)。

在重基之前,记录提交者的时间戳,作者的时间戳和所有将被重基到文件的提交的提交消息。

#NOTE: BASE is the commit where your rebase begins
git log --pretty='%ct %at %s' BASE..HEAD > hashlog

然后,让实际的调整发生。

最后,如果提交消息是相同的,我们使用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'

如果出现问题,只需签出git reflog或所有的refs/original/ refs。

此外,您可以对作者的时间戳做类似的事情。

例如,如果某些提交的作者的时间戳顺序乱了,那么 不需要重新排列这些提交,我们只需要显示作者的时间戳 顺序,那么下面的命令将有所帮助。

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'

真正的解决方案似乎来自Reddit。稍微放大一下,是这样的:

git -c rebase.instructionFormat='%s%nexec GIT_COMMITTER_DATE="%cD" git commit --amend --no-edit --allow-empty --allow-empty-message' rebase -i