如何在过去提交Git ?

我正在将所有内容转换为Git供我自己使用,我发现存储库中已经有一些旧版本的文件。我如何根据文件的“修改日期”将其以正确的顺序提交到历史记录中?这样我就有了档案的准确历史记录?

有人告诉我这样可行

git filter-branch --env-filter="GIT_AUTHOR_DATE=... --index-filter "git commit path/to/file --date " --tag-name-filter cat -- --all
182796 次浏览

你可以像往常一样创建提交,但是当你提交时,将环境变量GIT_AUTHOR_DATEGIT_COMMITTER_DATE设置为适当的日期时间。

当然,这将使提交位于分支的顶端(即,在当前HEAD提交的前面)。如果你想在回购中把它推得更远,你必须变得有点花哨。假设你有这样的历史:

o--o--o--o--o

你希望你的新提交(标记为“X”)显示第二个:

o--X--o--o--o--o

最简单的方法是从第一次提交开始分支,添加新提交,然后在新提交的基础上重新构建所有其他提交。像这样:

$ git checkout -b new_commit $desired_parent_of_new_commit
$ git add new_file
$ GIT_AUTHOR_DATE='your date' GIT_COMMITTER_DATE='your date' git commit -m 'new (old) files'
$ git checkout master
$ git rebase new_commit
$ git branch -d new_commit

给你的建议是有缺陷的。无条件地在--env-filter中设置GIT_AUTHOR_DATE将重写每次提交的日期。同样,在--index-filter中使用git提交也是不寻常的。

你在处理多个独立的问题。

指定“现在”以外的日期

每次提交都有两个日期:作者日期和提交者日期。可以通过通过环境变量GIT_AUTHOR_DATE和GIT_COMMITTER_DATE为写入新提交的任何命令提供值来覆盖它们。参见git-commit(1)中的“日期格式”或下面的内容:

Git internal format = <unix timestamp> <time zone offset>, e.g.  1112926393 +0200
RFC 2822            = e.g. Thu, 07 Apr 2005 22:13:13 +0200
ISO 8601            = e.g. 2005-04-07T22:13:13

在正常使用期间,唯一写入新提交的命令是git提交。它还有一个--date选项,可以让你直接指定作者日期。你的预期使用包括git filter-branch --env-filter还使用上面提到的环境变量(这些是“env”的一部分,选项在“env”之后命名;参见git-filter-branch中的“选项”(1)和底层的“管道”命令git-commit-tree (1)

插入一个文件到一个裁判历史记录

如果你的存储库非常简单(即你只有一个分支,没有标签),那么你可能可以使用git变基来完成这项工作。

在以下命令中,使用提交的对象名称(SHA-1哈希)而不是“A”。 当你运行git提交时,不要忘记使用一个“日期覆盖”方法。

---A---B---C---o---o---o   master


git checkout master
git checkout A~0
git add path/to/file
git commit --date='whenever'
git tag ,new-commit -m'delete me later'
git checkout -
git rebase --onto ,new-commit A
git tag -d ,new-commit


---A---N                      (was ",new-commit", but we delete the tag)
\
B'---C'---o---o---o   master

如果你想更新A以包含新文件(而不是在添加文件的地方创建新提交),那么使用git commit --amend而不是git commit。结果是这样的:

---A'---B'---C'---o---o---o   master

只要您能够命名应该作为新提交的父提交,上述方法就可以工作。如果你真的想要你的新文件通过一个新的根提交来添加(没有父节点),那么你需要一些不同的东西:

B---C---o---o---o   master


git checkout master
git checkout --orphan new-root
git rm -rf .
git add path/to/file
GIT_AUTHOR_DATE='whenever' git commit
git checkout -
git rebase --root --onto new-root
git branch -d new-root


N                       (was new-root, but we deleted it)
\
B'---C'---o---o---o   master

git checkout --orphan相对较新(Git 1.7.2),但有做同样事情的其他方法可用于较旧版本的Git。

将文件插入到Multi-裁判历史记录中

如果你的存储库更复杂(即它有多个ref(分支,标签等)),那么你可能需要使用git filter-branch。在使用git filter-branch之前,您应该为整个存储库创建备份副本。一个简单的焦油存档你的整个工作树(包括.git目录)就足够了。git filter-branch确实会做备份引用,但通常更容易从不太正确的过滤中恢复,只需删除你的.git目录并从备份中恢复它。

注意:下面的例子使用低级命令git update-index --add而不是git add。你可以使用git添加,但你首先需要将文件从某个外部位置复制到预期的路径(--index-filter在一个临时的GIT_WORK_TREE中运行它的命令,该GIT_WORK_TREE为空)。

如果你想要你的新文件被添加到每一个现有的提交,那么你可以这样做:

new_file=$(git hash-object -w path/to/file)
git filter-branch \
--index-filter \
'git update-index --add --cacheinfo 100644 '"$new_file"' path/to/file' \
--tag-name-filter cat \
-- --all
git reset --hard

我真的看不出有任何理由用--env-filter 'GIT_AUTHOR_DATE=…'改变现有提交的日期。如果你确实使用了它,你应该让它有条件,这样它就会为每次提交重写日期。

如果你想让你的新文件只出现在一些现有的提交(“A”)之后,那么你可以这样做:

file_path=path/to/file
before_commit=$(git rev-parse --verify A)
file_blob=$(git hash-object -w "$file_path")
git filter-branch \
--index-filter '


if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$before_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi


' \
--tag-name-filter cat \
-- --all
git reset --hard

如果你想通过插入到历史记录中间的新提交来添加文件,那么你需要在使用git filter-branch之前生成新的提交,并将--parent-filter添加到git filter-branch:

file_path=path/to/file
before_commit=$(git rev-parse --verify A)


git checkout master
git checkout "$before_commit"
git add "$file_path"
git commit --date='whenever'
new_commit=$(git rev-parse --verify HEAD)
file_blob=$(git rev-parse --verify HEAD:"$file_path")
git checkout -


git filter-branch \
--parent-filter "sed -e s/$before_commit/$new_commit/g" \
--index-filter '


if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$new_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi


' \
--tag-name-filter cat \
-- --all
git reset --hard

你也可以安排文件首先添加到一个新的根提交中:通过“orphan”方法从git变基部分创建你的新根提交(在new_commit中捕获它),使用无条件的--index-filter--parent-filter,如"sed -e \"s/^$/-p $new_commit/\""

在我的情况下,随着时间的推移,我已经保存了许多版本的myfile,如myfile_bak, myfile_old, myfile_2010, backups/myfile等。我想把我的文件的历史在git使用他们的修改日期。所以将最老的重命名为myfile, git add myfile,然后是git commit --date=(modification date from ls -l) myfile,将下一个最老的重命名为myfile,另一个git提交——date,重复…

为了实现自动化,你可以使用shell-foo来获取文件的修改时间。我从ls -lcut开始,但stat(1)更直接
git commit --date="`stat -c %y myfile`" myfile

在我的例子中,当使用——date选项时,我的git进程崩溃了。也许我做了什么可怕的事。结果是一些索引。出现锁文件。所以我手动删除了。git文件夹中的。lock文件并执行,所有修改过的文件都要在通过的日期内提交,这次它工作了。谢谢你的回答。

git commit --date="`date --date='2 day ago'`" -am "update"

我知道这个问题很老了,但这对我来说确实很管用:

git commit --date="10 day ago" -m "Your commit message"

以下是我用来在过去的fooN=1天提交更改的方法:

git add foo
git commit -m "Update foo"
git commit --amend --date="$(date -v-1d)"

如果你想提交一个更早的日期,比如3天前,只需更改date参数:date -v-3d

例如,当你忘记昨天提交某件事情时,这真的很有用。

更新: --date也接受像--date "3 days ago"甚至--date "yesterday"这样的表达式。所以我们可以把它压缩成一行命令:

git add foo ; git commit --date "yesterday" -m "Update"

你总是可以在你的计算机上更改日期,提交,然后更改日期并推送。

要让提交看起来像是过去完成的,你必须同时设置GIT_AUTHOR_DATEGIT_COMMITTER_DATE:

GIT_AUTHOR_DATE=$(date -d'...') GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" git commit -m '...'

其中date -d'...'可以是像2019-01-01 12:00:00这样的精确日期,也可以是像5 months ago 24 days ago这样的相对日期。

要查看git日志使用的两个日期:

git log --pretty=fuller

这也适用于合并提交:

GIT_AUTHOR_DATE=$(date -d'...') GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" git merge <branchname> --no-ff

或者只是使用fake-git-history来为特定的数据范围生成它。

这是一个老问题,但我最近偶然发现了它。

git commit --date='year-month-day hour:minutes:seconds' -m "message"
所以它看起来是这样的: git commit --date='2021-01-01 12:12:00' -m "message"工作正常,并在GitHubGitLab上验证了它

Pre-Step。< br >

  • 将所有数据从远程存储库拉到本地存储库。

  • 我们使用的是——modify和——date开关

具体命令如下:

$ git commit --amend --date="YYYY-MM-DD HH:MM:SS"

  1. git --date只改变GIT_AUTHOR_DATE,但许多git应用程序,例如,GitHub显示GIT_COMMITTER_DATE。一定要改变GIT_COMMITTER_DATE
  2. git在默认的UNIX日期输出中不知道时区。请确保将datetime格式格式化为兼容的格式,例如ISO8601。

OS X中的完整示例(将GIT_COMMITTER_DATEGIT_AUTHOR_DATE更改为4小时前):

x=$(date -v -4H +%Y-%m-%dT%H:%M:%S%z); export GIT_COMMITTER_DATE=$x; git commit --amend --date $x

你想要的简单答案:

GIT_AUTHOR_DATE="2020-10-24T18:00:00 +0200" GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE git commit

注意时区字符串,并为您的时区设置一个合适的字符串。即+0200,-0400