git 如何使用git仅暂存新文件的一部分?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6436681/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 05:35:47  来源:igfitidea点击:

How to stage only part of a new file with git?

git

提问by augustin

I lovegit add --interactive. It is now part of my daily workflow.

喜欢git add --interactive。它现在是我日常工作流程的一部分。

The problem seems that it does not work with untracked files. What I want to do is track a new file, but only add part of it, i.e. some parts of this new file are not yet ready to be staged.

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

For example, with git add -i, I can chose the patch option and even edit individual hunks in order to stage parts of the new code, leaving debug code comments unstaged. I love working this way because it makes it obvious which places of the mega patch I am currently working on still need work.

例如,使用 git add -i,我可以选择补丁选项,甚至可以编辑单个大块以暂存部分新代码,而不暂存调试代码注释。我喜欢以这种方式工作,因为它清楚地表明我目前正在处理的大型补丁的哪些地方仍然需要工作。

Unfortunately, I don't seem to be able to do the same with an untracked file. Either I stage the whole file, or nothing. The workaround I have been using is staging or even committing a new file when it is empty, and then staging individual changes in the usual way. But this solution feels like a dirty hack and when I forget, or change my mind, it creates more troubles than there should be.

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

So the question is: How to stage only part of a new file, so that this new file gets tracked but leaving the whole or parts of its content unstaged?

所以问题是:如何仅暂存新文件的一部分,以便跟踪该新文件,但不暂存其全部或部分内容?

回答by Richard Hansen

Whoa, all that update-indexand hash-objectbusiness seems overly complicated. How about this instead:

哇,所有这些update-indexhash-object业务似乎过于复杂。这个怎么样呢:

git add -N new_file
git add -i

From git help add:

来自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.

回答by sehe

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

Simple demo:

简单演示:

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

echo hello > newfile
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
  • HintIf you're sure the 'empty' blob already exists in your git object database, you could hardcode the hash e69de29bb2d1d6434b8b29ae775ad8c2e48c5391instead. I don't recommend doing that_
  • HintIf you're on Windows, you probably can just use NUL:instead of /dev/null. Otherwise, use something like echo -n '' | git hash-object --stdin -w
  • 提示如果您确定 git 对象数据库中已经存在“空” blob,则可以e69de29bb2d1d6434b8b29ae775ad8c2e48c5391改为对哈希进行硬编码。我不建议这样做_
  • 提示如果您使用的是 Windows,您可能可以使用NUL:代替/dev/null. 否则,使用类似echo -n '' | git hash-object --stdin -w

Now the index will contain newfileas the empty blob, and the empty blob has been entered into the object database if it didn't exist yet:

现在索引将包含newfile为空 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

This should be precisely what you want. May I also recommend the vim fugitive plugin for very intelligent index management (see Better git add -p?)

这应该正是您想要的。我还可以推荐用于非常智能的索引管理的 vim fugitive 插件(请参阅Better git add -p?

回答by Chronial

The easiest way to do this (and imho interactive staging in general) is git gui. It comes bundled with git and should work on almost all platforms that are supported by git.

执行此操作的最简单方法(以及一般的 imho 交互式登台)是git gui. 它与 git 捆绑在一起,几乎可以在 git 支持的所有平台上运行。

Simply run git guiand a gui will open that allows staging and unstaging hunks and even single lines of tracked and untracked files.

只需运行git gui并打开一个 gui,它允许暂存和取消暂存大块,甚至单行跟踪和未跟踪的文件。

Git Gui screenshot

Git Gui 截图

回答by dave1010

Edit:this doesn't seem to be working now. I'm sure it was before (on git 1.7.1). In case it doesn't work, I suggest staging /dev/nullas sehe suggests above:

编辑:这现在似乎不起作用。我确定它是以前的(在 git 1.7.1 上)。如果它不起作用,我建议/dev/null按照 sehe 上面的建议进行分期:

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

If you're on Windows (without /dev/null) then you can replace it with the path to an empty file.

如果您使用的是 Windows(没有/dev/null),那么您可以将其替换为空文件的路径。

Original answer

原答案

You want

你要

git add -p # (or --patch)

This adds untracked files for me. From the man page:

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

Interactively choose hunks of patch between the index and the work tree and add them to the index. This gives the user a chance to review the difference before adding modified contents to the index.

This effectively runs add --interactive, but bypasses the initial command menu and directly jumps to the patch subcommand. See “Interactive mode” for details.

在索引和工作树之间交互选择补丁块并将它们添加到索引中。这使用户有机会在将修改后的内容添加到索引之前查看差异。

这有效地运行 add --interactive,但绕过初始命令菜单并直接跳转到 patch 子命令。有关详细信息,请参阅“交互模式”。

回答by Pedro Adame Vergara

Just for the record of another possibility: I use

只是为了记录另一种可能性:我使用

git add -N file
git add -p file

And then you can stage hunks, or edit them in place.

然后你可以上演帅哥,或者就地编辑他们。