我正在将所有内容转换为Git供我自己使用,我发现存储库中已经有一些旧版本的文件。我如何根据文件的“修改日期”以正确的顺序将其提交到历史记录中,以便我拥有文件的准确历史记录?
有人告诉我这样可行
git filter-branch --env-filter="GIT_AUTHOR_DATE=... --index-filter "git commit path/to/file --date " --tag-name-filter cat -- --all
我正在将所有内容转换为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和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/\""。
在我的情况下,随着时间的推移,我保存了myfile的一堆版本,如myfile_bak, myfile_old, myfile_2010, backups/myfile等。我想把我的文件的历史在git使用他们的修改日期。所以将最老的重命名为myfile, git添加myfile,然后git提交——date=(从ls -l修改日期)myfile,将下一个最老的重命名为myfile,另一个git提交——date,重复…
为了实现某种程度上的自动化,您可以使用shell-foo来获取文件的修改时间。我从ls -l和cut开始,但stat(1)更直接 Git提交——date=" ' stat -c %y myfile ' " myfile
在我的例子中,当使用——date选项时,我的git进程崩溃了。也许我做了什么可怕的事。结果是一些索引。出现锁文件。所以我手动删除了。git文件夹中的。lock文件并执行,所有修改过的文件都要在通过的日期内提交,这次它工作了。谢谢你的回答。
git commit --date="`date --date='2 day ago'`" -am "update"
下面是我用来在过去N=1天提交对foo的更改:
git add foo
git commit -m "Update foo"
git commit --amend --date="$(date -v-1d)"
如果你想提交一个更早的日期,比如3天前,只需更改日期参数:date -v-3d。
例如,当你忘记昨天提交某件事情时,这真的很有用。
UPDATE:——date也接受像“3天前”这样的表达式,甚至是“昨天”这样的表达式。所以我们可以把它压缩成一行命令:
git add foo ; git commit --date "yesterday" -m "Update"
为了使提交看起来像过去完成的,你必须设置GIT_AUTHOR_DATE和GIT_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个月前的24天前。
要查看git日志使用的两个日期:
git log --pretty=fuller
这也适用于合并提交:
GIT_AUTHOR_DATE=$(date -d'...') GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" git merge <branchname> --no-ff
这是一个老问题,但我最近偶然发现了它。
git commit --date='year-month-day hour:minutes:seconds' -m "message"
所以它看起来是这样的: git commit——date='2021-01-01 12:12:00' -m "message"工作正常,并在GitHub和GitLab上进行了验证。
Pre-Step。
将所有数据从远程存储库拉到本地存储库。 我们正在使用——modify和——date开关。
具体命令如下:
$ git commit——modify——date="YYYY-MM-DD HH:MM:SS"
git——日期只更改GIT_AUTHOR_DATE,但许多git应用程序,例如,GitHub显示GIT_COMMITTER_DATE。确保也更改了GIT_COMMITTER_DATE。 git在默认的UNIX日期输出中不知道时区。请确保将datetime格式格式化为兼容的格式,例如ISO8601。
OS X中的完整示例(将GIT_COMMITTER_DATE和GIT_AUTHOR_DATE更改为4 hours ago):
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