我正在将所有内容转换为git以供自己个人使用,我在存储库中找到了一些旧版本。如何按照文件的“修改日期”以正确的顺序将其提交历史记录,以便我有准确的文件历史记录?

有人告诉我这样的事情会起作用:

git filter-branch --env-filter="GIT_AUTHOR_DATE=... --index-filter "git commit path/to/file --date " --tag-name-filter cat -- --all  
有帮助吗?

解决方案

您得到的建议是有缺陷的。无条件设置git_author_date --env-filter 将重写每个提交的日期。另外,使用将是不寻常的 git承诺 里面 --index-filter.

您在这里处理多个独立问题。

指定“现在”以外的其他日期

每个提交都有两个日期:作者日期和委员会日期。您可以通过环境变量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 rebase 做这项工作。

在以下命令中,使用提交的对象名称(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

只要您命名应为新提交的父母的提交,上面的工作就可以。如果您实际上希望通过新的root提交添加新文件(没有父母),那么您需要一些不同的东西:

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上工作。

将文件插入多参考 历史

如果您的存储库更复杂(即它具有多个Ref(分支,标签等)),那么您可能需要使用 git滤波器分支. 使用之前 git滤波器分支, ,您应该制作整个存储库的备份副本。 一个简单的 柏油 整个工作树的存档(包括.git目录)就足够了。 git滤波器分支 确实使备份参考 .git 目录并从备份中恢复它。

注意:下面的示例使用低级命令 git update-index --add 代替 git add. 。您可以使用 git添加, ,但是您首先需要将文件从某些外部位置复制到预期路径(--index-filter 在空为空的临时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滤波器分支 并添加 --parent-filtergit滤波器分支:

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

您还可以安排在新的根提交中首先添加文件:通过从 git rebase 部分(将其捕获 new_commit),使用无条件 --index-filter, ,a --parent-filter"sed -e \"s/^$/-p $new_commit/\"".

其他提示

您可以照常创建提交,但是当您提交时,设置环境变量 GIT_AUTHOR_DATEGIT_COMMITTER_DATE 到适当的数据。

当然,这将使您的分支尖端(即,在当前的头部提交)的尖端上提交。如果您想将其推回存储库,则必须有点花哨。假设您有这个历史:

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

我知道这个问题很老,但这实际上对我有用:

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

在我的情况下,随着时间的流逝,我保存了许多版本 myfile 如myfile_bak,myfile_old,myfile_2010,备份/myfile等。我想使用其修改日期将myfile的历史记录在git中。因此,重命名为最古老的myfile, git add myfile, , 然后 git commit --date=(modification date from ls -l) myfile, ,重命名为myfile的下一个年龄,另一个git with with - 日期,重复...

要自动化这一点,您可以使用Shell-Foo来获取文件的修改时间。我开始 ls -lcut, ,但是Stat(1)更直接

git commit --date="`stat -c %y myfile`" myfile

以下是我用来对更改进行更改的 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过程崩溃了。可能我做了一些可怕的事情。结果,出现了一些索引。因此,我从.git文件夹中手动删除了.lock文件并执行,以使所有修改的文件都在传递的日期中进行,并且这次起作用。在这里所有答案的thanx。

git commit --date="`date --date='2 day ago'`" -am "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

或者只使用命令行toolhttps://github.com/artiebits/fake-git-history为特定数据范围生成它

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top