Git能否提交新的、非空文件的“空版本”?

19
可以提交某些文件的空版本吗?具体情况是我需要将新(未跟踪的)非空文件首先添加并提交为“空”文件,以标记其内容为新内容并进行审查(完整的未跟踪文件不应添加到索引中; git diff应通过将文件与其提交的空版本进行比较来显示新添加的内容)。
有一个命令git add -N file...,它将file与空内容放入索引中,但这只表示file将被添加,git commit会抱怨文件尚未添加。问题在于当前的非空版本不是必须添加的内容,只需要新文件的空版本。
有没有办法做到这一点?
PS:这个问题是在一个程序自动向git仓库添加文件的背景下提出的(我的程序跟随代码学生编写)。未提交的代码是我尚未批准的代码。因此,由学生创建的程序的状态应该是“空”状态,即使我的程序只是在他们的主目录中找到了新的非空程序;这通过自动提交任何新的学生程序文件的新的空版本到git仓库来处理。因此,他们编写的新代码行显示为与上一个提交的git修订版相比的新添加内容。

1
我真的不明白你的问题。touch empty-file && git add empty-file && git commit 对我来说是有效的。 - joschi
git diff 在新创建的文件上可以正常工作。如果您在文件不存在时对其进行 diff,然后与其包含内容时进行 diff,则会看到所有添加的行,这与对空文件进行比较的精确相同的 diff(只有 modelines 不同)。 - Cascabel
1
@joschi:问题在于我有许多新的、非空文件。使用Sven的方法#1比使用他整洁的git-plumbing方法更麻烦。 - Eric O. Lebigot
@Jefromi: 我会有点害怕。 :) 如果学生想要的话,他们仍然可以自由地使用版本控制来管理自己的代码。版本控制软件足够灵活,可以做其他事情,这就是为什么我用它来标记应该与学生讨论的代码部分的原因。 - Eric O. Lebigot
注意:从 Git 2.5(2015 年第二季度)开始,git commit 将不再抱怨一个新文件“稍后要添加”:参见 https://dev59.com/XIfca4cB1Zd3GeqPeRvD#30341632。 - VonC
显示剩余5条评论
2个回答

37
说实话,我并不真正理解这有什么用。我会尝试修复审查流程而不是搞乱历史记录。但如果你真的想这样做,以下是几种方法:
  1. 实用主义方法:
  2. mv file out-of-way
    touch file
    git add file
    mv out-of-way file
    
  3. 瓷器方法:

  4. git add -N file
    git add -p file
    

    ...当被问及是否应该添加单个hunk时,只需回答“no”即可。(显然,这种方法在2019年已不再适用。)

  5. 管道方法:

    首先,确保对象数据库中存在一个空对象:

    git hash-object -w --stdin < /dev/null
    

    这将返回一个空blob的SHA1值(即e69de29bb2d1d6434b8b29ae775ad8c2e48c5391)。您只需创建此对象一次即可。现在,您可以通过以下方式在索引中创建空文件:

    git update-index --add --cacheinfo 0644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 file
    

1
@Sven:非常感谢!管道方法对我来说非常完美:它很容易自动化并直接了当(尽管为什么需要这样做的第二次猜测可能不太相关 :))。这对于跟踪学生在git diff上使用他们程序本地副本添加的新代码非常有用。未经批准的代码不应提交,但只要未提交(即未经批准),就会作为新增行出现(相对于空文件). - Eric O. Lebigot
@EOL:你也可以轻松地自动化触摸、添加和复制。 - Cascabel
@EOL:抱歉听起来有点不友善——只是想指出我不建议实际执行我在这个答案中解释的内容。我认为Jefromi在您的问题评论中提出的方法提供了更灵活(和更可靠)的工作流程。 - Sven Marnach
1
@EOL:我指的是Jefromi在您的问题评论中描述的工作流程,例如拥有单独的已提交已接受分支。这将是一种“修复审查过程”的方法,而不是“搞乱历史记录”。 - Sven Marnach
2
这里似乎不适用“瓷器方法”:git commit 显示 file: not added yet error: Error building trees,而 git stash 也出现了类似的错误。使用“管道方法”可以解决问题。 - p00ya
显示剩余6条评论

-2

自动添加所有空文件和文件夹


强制添加所有文件

$ git add -Af

你可以在每个空文件夹中自动添加.gitignore文件。

$ find $PATH_TO_REPOSITORY -type d ! -path "*.git*" -empty -exec cp .gitignore '{}'/ \;

您可以在每个空文件夹中自动添加 .gitkeep 文件

$ find $PATH_TO_REPOSITORY -type d ! -path "*.git*" -empty -exec touch '{}'/.gitkeep \;

1
嗨,Nathan。问题明确要求“非空”文件。你确定这不只是一个通用的复制粘贴答案吗? - minexew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接