我刚刚使用“git add -p”为索引添加了一堆更改,我才意识到我错过了应该进入上一次提交的更改。
我现在不能提交--amend因为我已经将所有这些新的更改添加到索引中,并且我不想使用'git reset'将它们全部从索引中删除,因为它需要很长时间才能将它们全部重新加入。
我需要的是像'git stash'这样只会隐藏索引的东西 - 它应该只保留工作文件。然后我可以存储索引,添加缺少的更改,提交它,然后弹出存储并使我的索引恢复原状。
它看起来不像'git stash'能够做到这一点,但我错过了什么吗?谢谢!
答案 0 :(得分:32)
我发现最接近的是git stash --patch
。它将引导您完成对工作树和索引的每个更改,以便您选择要存储的内容。
http://www.kernel.org/pub/software/scm/git/docs/git-stash.html
答案 1 :(得分:22)
最简单的方法是立即取消该更改,进行新的提交,然后创建第二个提交,只需要用于修改的更改,然后使用git rebase -i
将其与原始HEAD压缩。
另一种方法是进行提交,标记,回滚git reset HEAD^
,添加一个更改并修改HEAD,然后挑选标记的提交。
答案 2 :(得分:16)
为什么不作弊?
git stash --keep-index
将当前不在索引中的所有内容都删除。 然后,
git stash
只收集上演的内容。
git stash pop
第一个存储,添加您的更改。然后,
git commit --amend ...
git reset --hard
清理工作树然后
git stash pop --index
让您的索引更改回来。
答案 3 :(得分:9)
使用autosquash提交索引,创建修正提交和rebase:
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
答案 4 :(得分:9)
git stash
确实创建了一个包含索引内容的提交,然后添加了一个提交,其中包含所有跟踪文件的内容
要查看此内容:创建一个存储,然后运行
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
答案 5 :(得分:5)
这似乎有效。我没有在所有情况下对它进行测试以确保它的稳健性:
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]
答案 6 :(得分:5)
magit允许您使用命令magit-stash-index
执行此操作答案 7 :(得分:3)
这里的大多数答案都是相当复杂,危险的,或者并非在所有情况下都有效。在进行中时有很多更改(在索引和工作树中),我什至不想考虑硬重置,存储,过早地提交每个更改,只是为了使其恢复生命或其他应该起作用。我唯一想做的就是更改索引本身。
幸运的是,有一种简单的方法可以做到这一点!
git diff --cached > 1.diff
git reset
# add and commit changes that should be separate
git apply --cached 1.diff
就在那里!将当前索引另存为差异,将其重置,添加并提交单独的更改,然后将更改重新应用于保存的索引。
如果您要分离的更改已经应用到索引(并且您不想麻烦地删除它们),则必须在git reset HEAD^
之前使用一个附加的git apply
为了将索引重置为使用差异时的状态。否则,该补丁将不会再次应用(因为您的提交已经应用了该补丁),并且git
将绝对拒绝部分应用补丁。
答案 8 :(得分:2)
我必须这样做,最后使用了一些用于编写脚本的git存储选项。 Git stash create让你创建(但不应用)一个存储对象(包括索引)。 Git stash store将它添加到git stash堆栈而不进行git reset - 硬件存储保存隐式执行。这实际上,让你通过向存储库添加一个存储对象并手动重置索引来存储索引:
# 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。
有一点需要注意的是,创建的存储对象包括工作区和索引中更改的文件,即使您只关心索引,因此当您尝试从堆栈弹出时可能会发生冲突,即使你使用了--index标志(这意味着“也从存储中应用索引”,而不是“仅从存储中应用索引”)。在这种情况下,您可以在弹出之前执行“git reset --hard”(因为您重置的更改恰好与您刚刚弹出或立即应用的更改相同,因为它不像看来。)
答案 9 :(得分:1)
git stash -k
git stash
git stash apply stash@{1}
git stash drop stash@{1}
答案 10 :(得分:0)
这是我过去想出的一个小脚本来完成这个:
(注意:我最初是在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
,然后可以将其作为git stash-index
# <hack hack hack>
git add <files that you want to stash>
git stash-index
现在,存储包含一个新条目,该条目仅包含您已暂存的更改,而您的工作树仍包含任何未暂存的更改。
主要问题是您可能无法干净地删除索引更改而不会导致冲突,例如:如果工作树包含依赖于索引更改的更改。
在这种情况下,任何此类冲突将保留在通常的未合并冲突状态,类似于樱桃挑选/合并之后。
e.g。
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"
答案 11 :(得分:0)
如果添加准备提交到索引的文件,但只想登台,则可以使用下面的功能。
>> momomo.com.git.stash.added
或
>> momomo.com.git.stash.added "name of the stash"
bash功能:
momomo.com.git.stash.added() {
local name="$1";
if [[ "${name}" == "" ]]; then
name="$(date)"
fi
# This will stash everything, but let the added ones remain
# stash@{1}
git stash --keep-index
# This will stash only the remaining ones
# @stash@{0}
git stash save "${name}"
# Restore everything by applying the first push stash which is now at index 1
git stash apply stash@{1}
# Then drop it
git stash drop stash@{1}
# At the top of the stash should now be only the originally indexed files
}
请注意,您现在需要将内容重新添加到索引中。
答案 12 :(得分:0)
以下是(一种)简单食谱(至少要遵循):
git commit -m "Will come back and this will be removed, no worries"
git stash save "will drop it, no worries"
git reset --soft HEAD~1 # getting rid of previous revision
git stash save "this is what I really wanted to stash, set the right message"
git stash pop stash@{1} # get files that I didn't want to stash on the working tree