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

有人告诉我这样可行

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

当前回答

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

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

其他回答

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

Pre-Step。

将所有数据从远程存储库拉到本地存储库。 我们正在使用——modify和——date开关。

具体命令如下:

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

您可以像往常一样创建提交,但是在提交时,将环境变量GIT_AUTHOR_DATE和GIT_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 commit也不常见。

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

指定“现在”以外的日期

每次提交都有两个日期:作者日期和提交者日期。可以通过通过环境变量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 commit。它还有一个——date选项,可以让您直接指定作者日期。你预期的使用包括git过滤器分支——env-filter也使用上面提到的环境变量(这些是“env”的一部分,选项在“env”之后命名;参见git-filter-branch(1)中的“Options”和底层的“plumbing”命令git-commit-tree(1)。

插入一个文件到一个单独的引用历史

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

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

---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检出——孤儿是相对较新的(git 1.7.2),但是在旧版本的git上有其他方法可以做同样的事情。

将文件插入到多引用历史记录中

If your repository is more complex (i.e. it has more than one ref (branches, tags, etc.)), then you will probably need to use git filter-branch. Before using git filter-branch, you should make a backup copy of your entire repository. A simple tar archive of your entire working tree (including the .git directory) is sufficient. git filter-branch does make backup refs, but it is often easier to recover from a not-quite-right filtering by just deleting your .git directory and restoring it from your backup.

注意:下面的例子使用低级命令git update-index——add而不是git add。你可以使用git add,但你首先需要将文件从某个外部位置复制到预期的路径(——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之前生成新的提交,并在git filter-branch中添加——parent-filter:

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部分的“orphan”方法创建新的根提交(在new_commit中捕获它),使用无条件的——index-filter和——parent-filter,如"sed -e \"s/^$/-p $new_commit/\""。

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

git commit --date='year-month-day hour:minutes:seconds' -m "message"

所以它看起来是这样的: git commit——date='2021-01-01 12:12:00' -m "message"工作正常,并在GitHub和GitLab上进行了验证。