如何用git只阶段一个新文件的一部分?

我__abc0 __abc1。现在这是我日常工作流程的一部分。

问题似乎是,它不能对未跟踪的文件工作。我想要做的是跟踪一个新文件,但只添加它的一部分,即这个新文件的某些部分还没有准备好登台。

例如,使用git add -i,我可以选择补丁选项,甚至可以编辑单独的块,以便阶段性地展示新代码的一部分,而不显示调试代码注释。我喜欢这种工作方式,因为它让我很明显地知道我目前正在制作的大型补丁中哪些地方还需要改进。

不幸的是,对于未跟踪的文件,我似乎无法做到这一点。要么我把文件全部放出来,要么什么都不放。我一直在使用的解决方法是在新文件为空时暂存,甚至提交新文件,然后以通常的方式暂存各个更改。但这个解决方案感觉像一个肮脏的hack,当我忘记,或改变我的想法,它创造了更多的麻烦比应有的。

因此,问题是:如何只显示新文件的一部分,以便跟踪这个新文件,而不显示其全部或部分内容?

20550 次浏览
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
git add --interactive newfile

简单的演示:

mkdir /tmp/demo
cd /tmp/demo
git init .


echo hello > newfile
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
  • 如果你确定'empty' blob已经存在于你的git对象数据库中,你可以硬编码哈希e69de29bb2d1d6434b8b29ae775ad8c2e48c5391。我不建议那样做
  • 如果你在Windows上,你可能只能使用__ABC0而不是__ABC1。否则,使用类似echo -n '' | git hash-object --stdin -w的东西

现在索引将包含newfile作为空blob,如果空blob还不存在,则该空blob已被输入到对象数据库:

子> <

$ find .git/objects/ -type f
.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391


$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   newfile
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   newfile
#


$ git diff
diff --git a/newfile b/newfile
index e69de29..ce01362 100644
--- a/newfile
+++ b/newfile
@@ -0,0 +1 @@
+hello

这应该正是你想要的。我还可以推荐vim逃犯插件非常智能的索引管理(见更好的git add -p?)

编辑:这似乎不工作现在。我敢肯定是在git 1.7.1之前。以防它不起作用,我建议按照上面她的建议进行/dev/null:

git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile

如果你在Windows上(没有/dev/null),那么你可以用一个空文件的路径替换它。

原来的答案

你想要的

git add -p # (or --patch)

这为我添加了未跟踪的文件。从手册页:

交互选择补丁块 在索引和工作树之间 并将它们添加到索引中。这给了 用户有机会审查 添加前差异已修改

这有效地运行add ——交互,但绕过初始的命令菜单和直接 跳转到补丁子命令。看到

.

.

哇,所有update-indexhash-object的事情看起来太复杂了。不如这样吧:

git add -N new_file
git add -i  # or 'git add -p' if you prefer

git help add:

-N, --intent-to-add
Record only the fact that the path will be added later.  An entry
for the path is placed in the index with no content.  This is useful
for, among other things, showing the unstaged content of such files
with git diff and committing them with git commit -a.

最简单的方法是git gui。它与git捆绑在一起,应该可以在git支持的几乎所有平台上工作。

只需运行git gui,就会打开一个gui,允许分段和取消分段块,甚至单行跟踪和未跟踪文件。

Git Gui截图

只是为了记录另一种可能性: 我使用< / p >
git add -N file
git add -p file

然后你就可以摆出大块头,或者就地编辑它们。