2011-06-22 63 views
167

I git add --interactive。它现在是我日常工作流程的一部分。如何仅使用git分阶段创建新文件?

问题似乎是,它不适用于未跟踪的文件。我想要做的是跟踪一个新文件,但只添加它的一部分,即这个新文件的某些部分尚未准备好上演。

例如,使用git add -i,我可以选择修补程序选项,甚至可以编辑个别区块,以便部署新代码,从而使调试代码注释处于非持续状态。我喜欢这样工作,因为它明确了我目前正在进行的大型补丁的哪些地方仍然需要工作。

不幸的是,我似乎无法对未跟踪的文件做同样的事情。要么是整个文件,要么没有。我一直在使用的解决方法是暂存或甚至在空文件时提交一个新文件,然后以通常的方式暂存各个更改。但是这个解决方案感觉像一个肮脏的黑客,当我忘记,或改变主意时,它会产生比应该更多的麻烦。

所以问题是:如何仅阶段的一部分新文件,以便这个新文件得到跟踪,但留下整个或其内容的一部分未分离?

+22

哪个部分是'1'还是'0'? –

+5

@Ignacio:我认为你不要使用Git登台区域 – sehe

+7

...今晚艰难的人群... –

回答

308

哇,所有那update-indexhash-object业务似乎过于复杂。这个怎么样,而不是:

git add -N new_file 
git add -i 

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

++ 1!应有的信贷。我相信有点太多,我现在知道这些手册页......'' – sehe

+0

@sehe:好的呼吁添加手册页片断,谢谢! –

+1

找到了。我应该更进一步滚动手册页。也许我应该返回Git Pro徽章。 – dave1010

6
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 
  • 提示如果你确定了 '空' 的blob已经存在于你的git对象数据库,你可以硬编码的哈希e69de29bb2d1d6434b8b29ae775ad8c2e48c5391代替。我不建议这样做that_
  • 提示如果您使用的是Windows,你大概可以只使用NUL:,而不是/dev/null。否则,使用类似echo -n '' | git hash-object --stdin -w

现在,该指数将包含newfile为空的斑点,而斑点空已进入对象数据库,如果不存在,就:

$ 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 fugitive插件(请参阅Better git add -p?

+1

这似乎工作得很好。我已经把它命名为“stage-empty-file”,因为它有点复杂。 – dave1010

+1

不错+1。[6更多] –

+0

@ dave1010:很高兴它帮助! _是的,我想添加一个别名,但我不知道你期望如何处理通配符或多个文件名参数。所以我选择不要_ – sehe

2

编辑:这似乎不工作。我确定它是之前(在git 1.7.1上)。如果它不工作,我建议分期/dev/null作为sehe以上建议:

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

如果您使用的是Windows(不/dev/null),那么你可以与路径设置为空文件替换它。

原来的答复

你想

git add -p # (or --patch) 

这增加了未跟踪文件给我。从手册页:

交互式选择索引和工作树之间 补丁 的帅哥,并将它们添加到索引。这给 用户提供了一个机会,在将修改后的 内容添加到索引之前查看 差异。

这有效地运行添加 - 交互,但绕过最初的命令菜单,并直接跳转到patch子命令 。详情请参阅 “交互模式”。

+2

然而有趣的是,它不适合我(git 1.7.4); 'git add -p newfile'根本不起作用(nu效果)和'git add --interactive''[a] dd untracked'的效果是'git add newfile' has; **编辑**也使用git 1.7.5.3进行了检查;没有骰子 – sehe

+0

Windows的好提示,在我的答案中增加了提示。 Thx – sehe

4

最简单的方式做到这一点(和一般恕我直言互动分期)是git gui。它与git捆绑在一起,应该可以在git支持的几乎所有平台上运行。

只需运行git gui即可打开一个gui,它允许登台和暂停hunk以及单行跟踪和未跟踪的文件。

Git Gui screenshot

+0

这是一个创造性的答案,有时这非常非常有用。 –

+2

请注意,并非所有的git发行版都包含'git gui'。例如,在Debian中,它位于一个名为“git-gui”的单独包中。 – cristoper

+0

这个功能多年来一直在寻找(不够困难),这是一个改变生活的人 – austinmarton