这是我过去想出的一个小脚本,可以做到这一点:
(注意:我最初将此内容发布在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
现在,存储区包含一个新条目,该条目仅包含您已暂存的更改,而工作树仍包含任何未暂存的更改。
主要问题是,您可能无法干净地删除索引更改而不引起冲突,例如,如果工作树包含依赖于索引更改的更改。
在这种情况下,任何此类冲突都将保留在通常的未合并冲突状态中,类似于在执行摘樱桃/合并之后。
例如
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"
git commit您想要的-它需要您的索引并从中创建一个提交。凯文·巴拉德(Kevin Ballard)的答案解释了在这样做之后如何合理地重写历史……