我如何在过去做Git commit? [英] How do I make a Git commit in the past?

查看:90
本文介绍了我如何在过去做Git commit?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我被告知像这样的工作:

  git过滤器-branch --env-filter =GIT_AUTHOR_DATE = ... --index-filtergit commit path / to / file --date--tag-name-filter cat  -  --all 
code>


解决方案

您给出的建议有缺陷。无条件地将GIT_AUTHOR_DATE设置在 - env-filter 会重写每一次提交的日期,并且在 - index->​​中使用 git commit 过滤器



您正在处理多个独立的问题。

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

  Git内部格式=< unix timestamp> ; <时区偏移>例如, 1112926393 +0200 
RFC 2822 =例如星期四,07 Apr 2005 22:13:13 +0200
ISO 8601 =例如2005-04-07T22:13:13

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



将文件插入单个历史记录



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



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

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

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

--- A --- N(是,new-commit ,但我们删除了标签)
\
B'--- C'--- o --- o --- o master

如果您想更新A以包含新文件(而不是在添加新文件的位置创建新提交文件),请使用 git提交--amend 而不是 git commit 。结果如下所示:

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

只要你可以命名提交,应该是新提交的父项。如果您确实希望通过新的根提交(无父母)添加新文件,那么您需要一些不同的内容:

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

git checkout master
git checkout --orphan新根
git rm - rf。
git add path / to / file
GIT_AUTHOR_DATE ='whatever'git commit
git checkout -
git rebase --root --onto new-root
git branch -d新根

N(是新根,但我们删除了它)
\
B'--- C'--- o --- o --- o master

git checkout --orphan 是相对较新的(Git 1.7.2),但也有做同样事情的其他方法

a>在旧版本的Git上工作。



将文件插入到Multi- ref 历史记录



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



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

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


$ b $

  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;然后
git update-index --add --cacheinfo 100644'$ file_blob $ file_path''
fi

'\
--tag-name-过滤猫\
- --all
git reset --hard

如果你想通过一个新的提交来添加文件,这个提交将被插入到你的历史中间,那么你需要在使用 git filter-branch 之前生成新的提交并添加 - parent-filter to 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 ='whatever'
new_commit = $(git rev-parse --verify HEAD)
file_blob = $(git rev -parse --verify HEAD:$ file_path)
git checkout -

git filter-branch \
--parent-filtersed -es / $ before_commit / $ new_commit / g\
--index-filter'

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

'\
--tag-name-过滤猫\
- --all
git reset --hard

您还可以安排将文件首次添加到新的根提交中:通过 git rebase 部分的orphan方法创建新的根提交(将其捕获到 new_commit ),使用无条件的 - index-filter - parent-filter like sed -e \s / ^ $ / - p $ new_commit / \


I'm converting everything over to Git for my own personal use and I found some old versions of a file already in the repository. How do I commit it to the history in the correct order according the the file's "date modified" so I have an accurate history of the file?

I was told something like this would work:

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

解决方案

The advice you were given is flawed. Unconditionally setting GIT_AUTHOR_DATE in an --env-filter would rewrite the date of every commit. Also, it would be unusual to use git commit inside --index-filter.

You are dealing with multiple, independent problems here.

Specifying Dates Other Than "now"

Each commit has two dates: the author date and the committer date. You can override each by supplying values through the environment variables GIT_AUTHOR_DATE and GIT_COMMITTER_DATE for any command that writes a new commit. See "Date Formats" in git-commit(1) or the below:

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

The only command that writes a new commit during normal use is git commit. It also has a --date option that lets you directly specify the author date. Your anticipated usage includes git filter-branch --env-filter also uses the environment variables mentioned above (these are part of the "env" after which the option is named; see "Options" in git-filter-branch(1) and the underlying "plumbing" command git-commit-tree(1).

Inserting a File Into a Single ref History

If your repository is very simple (i.e. you only have a single branch, no tags), then you can probably use git rebase to do the work.

In the following commands, use the object name (SHA-1 hash) of the commit instead of "A". Do not forget to use one of the "date override" methods when you run git commit.

---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

If you wanted to update A to include the new file (instead of creating a new commit where it was added), then use git commit --amend instead of git commit. The result would look like this:

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

The above works as long as you can name the commit that should be the parent of your new commit. If you actually want your new file to be added via a new root commit (no parents), then you need something a bit different:

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 is relatively new (Git 1.7.2), but there are other ways of doing the same thing that work on older versions of Git.

Inserting a File Into a Multi-ref History

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.

Note: The examples below use the lower-level command git update-index --add instead of git add. You could use git add, but you would first need to copy the file from some external location to the expected path (--index-filter runs its command in a temporary GIT_WORK_TREE that is empty).

If you want your new file to be added to every existing commit, then you can do this:

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

I do not really see any reason to change the dates of the existing commits with --env-filter 'GIT_AUTHOR_DATE=…'. If you did use it, you would have make it conditional so that it would rewrite the date for every commit.

If you want your new file to appear only in the commits after some existing commit ("A"), then you can do this:

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

If you want the file to be added via a new commit that is to be inserted into the middle of your history, then you will need to generate the new commit prior to using git filter-branch and add --parent-filter to 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

You could also arrange for the file to be first added in a new root commit: create your new root commit via the "orphan" method from the git rebase section (capture it in new_commit), use the unconditional --index-filter, and a --parent-filter like "sed -e \"s/^$/-p $new_commit/\"".

这篇关于我如何在过去做Git commit?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆