你怎么告诉git只存储索引?

我刚刚使用“git add -p”向索引添加了一堆更改,而我只是意识到我错过了应该进入前一个提交的更改。

我现在不能提交,因为我已经将所有这些新的更改添加到索引,我不希望使用'git reset'将它们全部从索引中删除,因为它需要很长时间才能将它们全部添加回来了。

我需要的就是像“git stash”那样只会隐藏索引 – 它应该保留工作文件。 然后,我可以隐藏索引,添加缺失的变化,提交它,然后popup存储并使索引恢复原样。

它看起来不像“混帐”能够做到这一点,但我错过了什么? 谢谢!

最简单的方法是立即停止更改,创build新的提交,然后创build第二个提交,只需要修改该更改,然后使用git rebase -i将它与原始HEAD进行压缩。

另一种方法是做你的提交,标记它,用git reset HEAD^回滚,添加一个改变并修改HEAD,然后select你的标记提交。

我find的最接近的东西就是git stash --patch 。 它引导您通过对工作树和索引的每个更改,让您select要存储的内容。

http://www.kernel.org/pub/software/scm/git/docs/git-stash.html

提交你的索引,创build一个修复提交,并使用autosquash重定位:

 git commit git add -p # add the change forgotten from HEAD^ git commit --fixup HEAD^ # commits with "fixup! <commit message of HEAD^>" git rebase --autosquash -i HEAD~3 

git stash实际上是创build一个提交的索引内容,然后添加一个提交的所有跟踪文件的内容在它的顶部

要查看这个:创build一个存储,然后运行

 git log --oneline --graph stash@{0} 

所以从技术上讲,当你存储的时候,你可以通过stash@{0}^2取回你的索引:

 $ git show --name-only stash@{0}^2 $ git checkout stash@{0}^2 -- . 

您也可以隐藏,然后获取已追踪但未添加的文件的内容:

 # get the diff between what was indexed and the full stashed content : $ git diff -p stash@{0}^2 stash@{0} > diff.patch # apply this diff : $ git apply diff.patch 

这似乎工作。 我没有在所有情况下testing它,以确保它是健壮的:

 git commit -m _stash && git stash && git reset HEAD^ && git stash save && git stash pop stash@{1} 

但是,它会临时有效地提交索引,存储工作目录,还原提交以获取索引,将其另存为另一个存储,然后从存储中再次恢复原始工作目录。

通过添加这个作为git别名来简化:

 [alias] istash = "!f() { git commit -m _stash && git stash && git reset HEAD^ && git stash save $1 && git stash pop stash@{1}; }; f" 

这允许我使用它,如:

 git istash [optional stash name] 

解决scheme1:

为什么不作弊?

 git stash --keep-index 

把目前不在索引中的所有东西都拿出来。 然后,

 git stash 

只保留上演的东西。

 git stash pop 

第一个存储,添加您的更改。 然后,

 git commit --amend ... git reset --hard 

清理工作树,然后

 git stash pop --index 

让您的索引更改回来。

用于emacs的magit可以让你用命令magit -stash-index来做到这一点

我必须这样做,并最终使用一些用于脚本的git存储选项。 Git存储创build让我们创build(但不是应用)一个存储对象(其中包括索引)。 Git存储存储将其添加到git存储堆栈,而不做git重置 – 哈希git存储保存隐含。 这实际上让我们通过向堆栈添加一个存储对象并手动重置索引来存储一个索引:

 # This will add an entry to your git stash stack, but *not* modify anything git stash store -m "Stashed index" $(git stash create) # This will reset the index, without touching the workspace. git reset --mixed 

你现在已经有效地隐藏了你的索引,当你完成的时候可以做一个git stash pop – index。

一个需要注意的是,即使您只关心索引,所创build的存储对象也包含在工作区中更改的文件和索引,所以即使使用 – 索引标志(意思是“也适用于隐藏索引”,而不是“只应用隐藏索引”)。 在这种情况下,您可以在popup之前执行“git reset –hard”(因为您正在重置的更改与您刚才popup或应用的更改相同,所以不会像它似乎。)

这里有一个我以前想到的小脚本来完成这个工作:

(注意:我最初是在https://stackoverflow.com/a/17137669/531021上发布的,但是它似乎也适用于这里,这些并不是完全重复的问题,所以我认为它在两个方面都是可能的答案例);

 #!/bin/sh # first, go to the root of the git repo cd `git rev-parse --show-toplevel` # create a commit with only the stuff in staging INDEXTREE=`git write-tree` INDEXCOMMIT=`echo "" | git commit-tree $INDEXTREE -p HEAD` # create a child commit with the changes in the working tree git add -A WORKINGTREE=`git write-tree` WORKINGCOMMIT=`echo "" | git commit-tree $WORKINGTREE -p $INDEXCOMMIT` # get back to a clean state with no changes, staged or otherwise git reset -q --hard # Cherry-pick the index changes back to the index, and stash. # This cherry-pick is guaranteed to suceed git cherry-pick -n $INDEXCOMMIT git stash # Now cherry-pick the working tree changes. This cherry-pick may fail # due to conflicts git cherry-pick -n $WORKINGCOMMIT CONFLICTS=`git ls-files -u` if test -z "$CONFLICTS"; then # If there are no conflicts, it's safe to reset, so that # any previously unstaged changes remain unstaged # # However, if there are conflicts, then we don't want to reset the files # and lose the merge/conflict info. git reset -q fi 

你可以把上面的脚本保存为git-stash-index到你的path的某个地方,然后可以调用它作为git stash-index

 # <hack hack hack> git add <files that you want to stash> git stash-index 

现在隐藏包含一个新的条目,只包含您已经进行的更改,并且您的工作树仍然包含任何unstaged的更改。

主要的问题是,如果工作树包含依赖索引的更改的更改,则可能无法清除地删除索引更改而不引起冲突。

在这种情况下,任何这样的冲突都会留在通常没有进入的冲突状态,类似于挑选/合并之后。

例如

 git init echo blah >> "blah" git add -A git commit -m "blah" echo "another blah" >> blah git add -A echo "yet another blah" >> blah # now HEAD contains "blah", the index contains "blah\nanother blah" # and the working tree contains "blah\nanother blah\nyetanother blah" git stash-index # A new stash is created containing "blah\nanother blah", and we are # left with a merge conflict, which can be resolved to produce # "blah\nyet another blah"