在保留提交时间戳的同时执行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中是否允许有历史记录,即旧的提交有最近的提交作为父?
默认情况下,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'
默认情况下,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'
post-rewrite钩
这个钩子适用于所有的git rebase, git pull -rebase和git commit -amend。
. / / post-rewrite hook
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上游。
别忘了:
chmod +x .git/hooks/post-rewrite
这是一种很好的方法——在选定的回购上默认设置committer-date-is-author-date,直到有人最终修补配置以默认设置它。
它还可以用。committer-date-is-author-date,这似乎不会在git pull时暴露。
参见:
什么git挂钩适用于'git rebase -continue'?
男人githooks
在git 2.19, Ubuntu 18.04上测试。