【问题标题】:How to add a file to the first commit on a git repo?如何将文件添加到 git repo 的第一个提交中?
【发布时间】:2011-09-03 19:52:49
【问题描述】:

我一直在将旧的 SVN 存储库转换为 GIT。我已经得到了要转换的分支和标签。包括在GIT中制作SVN标签真正的标签。

但是,我想在新创建的 GIT 存储库中的第一个提交中添加一个 gitignore。我希望它就像文件一直在那里一样。因此,随后的所有提交(在主节点或分支中)现在都将具有此文件,因为父树将引导回第一个提交。

似乎某种形式的 git rebase 或 git filter-branch --tree-filter 是我需要的。我已经尝试了其中的每一个,但我最终得到了断开连接的分支。

【问题讨论】:

  • 您可以使用git rebase -i 轻松为单个分支执行此操作。但我不确定如何对整个仓库中的所有分支和标签执行此操作。
  • 是的。对于一个分支来说,这很容易。我真的想“改写”历史。我想让它就好像我从一开始就添加了 gitignore,一切都从那里开始。

标签: git rebase


【解决方案1】:

如果将来有人需要这样做,这里有一个更简单的解决方案。由于提交消息中有问题,我最近不得不修改早期提交。这适用于更改有关先前提交的任何内容。我修改了Charles Bailey的答案here

# Go back to the commit you want to change (detach HEAD)
git checkout <sha1_for_commit_to_change>

# Make any changes now (add your new file) then add them to the index
git add <new_files>

# amend the current commit
git commit --amend

# temporarily tag this new commit
# (or you could remember the new commit sha1 manually)
git tag tmp

# go back to the original branch (assume master for this example)
git checkout master

# Replay all the commits after the change onto the new initial commit
git rebase --preserve-merges --onto tmp <sha1_for_commit_to_change>

# remove the temporary tag
git tag -d tmp

请注意,这将在修改后的提交后更改您的所有提交 ID,因此不建议在公共存储库中使用。此外,您必须重新创建所有标签

【讨论】:

    【解决方案2】:

    在干净的工作树上执行此操作,如果您愿意,可以在新的克隆上:

    $ git checkout -b withgitignore $firstcommithash
    $ git add .gitignore
    $ git commit --amend
    $ for branch in branch1 branch2 branch3 ... ; do
          git checkout $branch
          git rebase withgitignore
       done
    

    未经测试;)

    【讨论】:

    • 我会试一试并报告。
    • 我能想到它为什么不起作用的唯一原因是因为一个或多个分支(或标签指向的提交)没有共享相同的第一次提交。您能否通过执行“git log --oneline branch|tail -1”之类的操作来验证情况是否如此?比较所有分支和标签的结果。
    • 抱歉耽搁了。老婆早产很忙!我检查了每个分支/标签,每个分支/标签都有相同的第一次提交。我会再试一次,看看能不能提供更多信息。
    • 恭喜你成为父亲!请告诉你的妻子,一个陌生人祝你全家万事如意。作为两个孩子的父亲,我只能说孩子能给你带来无法估量的幸福。
    • 好吧,我又试了一次,还是不行。它经历了这些动作,但是当我切换/签出它们时,gitignore 文件不在任何分支或标签中。哦,谢谢你的祝福。 2个孩子也适合我。绝对不是线性难度曲线!更难。
    【解决方案3】:

    假设这是一个全新的重建,那么一个技巧是在第一次提交时启动一个分支并在那里添加 gitignore。您现在在该分支的头部有了“正确”的提交。现在要诀窍了——您使用grafts 工具对感知到的提交序列进行重新排序。一个普通的git filter-branch 将使其永久化,尽管旧的层次结构仍将在 refs\info (IIRC) 中的originals 下列出。

    虽然这将创建一个包含 gitignore 文件的早期提交,但所有其他提交仍然没有 gitignore 文件。

    编辑:--------- git-filter-branch,举例:

    git filter-branch --tree-filter 'rm filename' HEAD--index-filter 变体。

    您可以简单地 add .gitignore 您的 .gitignore 而不是删除,并使用 --index-filter 以便您的工作树仍然完好无损,可以从中复制。

    请确保您先备份! 报告它是否适合您。

    【讨论】:

    • 嗯。似乎这仍然无助于其他提交。与其说我想要重新排序提交,不如说我希望实现一些允许其他提交“继承”新添加的文件的东西。我会阅读更多关于 --index-filter 的内容,以防我误解。
    • 该命令应该做的是逐个检查每个提交,并执行过滤操作,在这种情况下是添加您的.gitignore,然后重新编写提交。在命令的最后,如果你使用gitk --all,你应该看到新形成的分支,每个提交都包含.gitignore,加上一个originals伪分支'以防万一'。
    • 我尝试将 gitignore 复制到工作树中,然后复制 git filter-branch --tree-filter 'git add gitignore' HEAD --index-filter,但我收到此错误:fatal: ambiguous argument 'add': unknown revision or path not in the working tree。
    • @Carl:tree-filter 是手册页示例。您是否尝试过建议的--index-filter?即假设git filter-branch --index-filter 'git add gitignore' HEAD(是.gitignore,还是简单的gitignore?)
    • 抱歉耽搁了。老婆早产很忙!无论如何,我尝试了git filter-branch --index-filter 'git add gitignore' HEADgit filter-branch --index-filter 'git add gitignore'git filter-branch --index-filter 'git add .gitignore',但在每种情况下仍然出现相同的错误
    猜你喜欢
    • 1970-01-01
    • 2017-07-18
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    • 2019-07-21
    • 2016-08-01
    • 2016-10-08
    • 1970-01-01
    相关资源
    最近更新 更多