在git中交换阶段性和非阶段性更改的最短方法是什么?

在git中交换阶段性和非阶段性更改的最短方法是什么?,git,Git,如果将某些更改添加到索引中,而有些更改未添加到索引中,如何交换这两组更改?涉及提交和管理潜在冲突解决 我最初只尝试使用git stash,但我最初忽略的是git stashsave将同时保存索引(分段更改)和未分段更改(当您想用未分段更改交换索引内容时,这很不方便) 因此,我改为采用以下方法: git commit-m“临时提交”(为当前索引创建提交) git隐藏(显然隐藏尚未添加到索引中的内容) git重置--软头^(保留以前提交的文件) git隐藏再次 git stash pop stas

如果将某些更改添加到索引中,而有些更改未添加到索引中,如何交换这两组更改?

涉及提交和管理潜在冲突解决

我最初只尝试使用
git stash
,但我最初忽略的是
git stash
save将同时保存索引(分段更改)和未分段更改(当您想用未分段更改交换索引内容时,这很不方便)

因此,我改为采用以下方法:

  • git commit
    -m“临时提交”(为当前索引创建提交)
  • git隐藏
    (显然隐藏尚未添加到索引中的内容)
  • git重置--软头^
    (保留以前提交的文件)
  • git隐藏
    再次
  • git stash pop stash@{1}
    (应用的不是刚刚隐藏的内容,而是之前隐藏的内容,即尚未添加到索引中的初始更改)
  • git add-A
  • git stash drop stash{1}
    清理我们之前应用的隐藏(stash{0}仍然包含索引中最初的内容)
最后:

  • 未添加到索引中的内容现在已添加
  • 最初在索引中的内容最终被隐藏起来

它认为这是使用临时提交最容易做到的。当您进行了暂存和未暂存的提交时,在尝试重新排序更改时可能会发生冲突

使用阶段性更改进行提交,创建分支供以后使用:

git commit -m "Saved staged"
git branch save-staged
使用未老化的更改进行提交(如果未老化的更改包括新文件,您可能需要先显式地
git添加它们):

将未定格的更改重新定格到原始标题上(可能涉及冲突解决):

将阶段性变更重新设定为未阶段性变更(可能涉及冲突解决):

最后,将索引重置为(最初)未分级的更改:

git reset HEAD^
并将分支指针移回原始标头:

git reset --soft HEAD^
已移除的临时分支:

git branch -D save-staged
修补程序的方式(不适用于二进制更改):

保存分段和未分段状态的修补程序

git diff >> unstaged.patch
git diff --cached >> staged.patch
应用最初未老化的更改

git reset --hard
git apply unstaged.patch
暂存此更改,修补程序文件除外

git add -A
git reset -- staged.patch unstaged.patch
rm staged.patch unstaged.patch
应用最初阶段的更改

git apply staged.patch
删除修补程序文件

git add -A
git reset -- staged.patch unstaged.patch
rm staged.patch unstaged.patch

对于较低级别的解决方案,可以使用一些管道直接与索引对话:

INDEXTREE=`git write-tree`
git add -A
WORKTREE=`git write-tree`
git checkout $INDEXTREE -- .
git clean -f
git read-tree $WORKTREE
这样做的目的是在git存储中构建两个临时树对象,一个用于索引,另一个用于工作副本。然后,它恢复旧索引并将其签出到工作树中。最后它将索引重置为表示旧工作树的版本

我还没有测试过它,所以我不确定它在索引或工作树中处理添加的文件的效果如何。

这是基于,但在暂存新文件时效果更好。这将用作脚本,例如,
git invert index

#!/bin/sh

# first, go to the root of the git repo
pushd `git rev-parse --show-toplevel`

# write out a tree with only the stuff in staging
INDEXTREE=`git write-tree`

# now write out a tree with everything
git add -A
ALL=`git write-tree`

# get back to a clean state with no changes, staged or otherwise
git reset -q --hard
git clean -fd

# apply the changes that were originally staged, that we want to
# be unstaged
git checkout $INDEXTREE -- .
git reset

# apply the originally unstaged changes to the index
git diff-tree -p $INDEXTREE $ALL | git apply --index --reject

# return to the original folder
popd

git-stash
意味着一个
git-reset--hard
所以
git-reset--mixed
是不可操作的,第二个
git-stash
与此无关?@Charles:对。我已经将答案更新为使用
git stash--keep index
。这样一来,
git reset--mixed
就有了作用;)好的,但是不是
git drop stash@{1}
肯定是不正确的,如果您的过程中的最后一步是
git add-A
,那么您不会以任何未过时的更改结束吗?我不相信隐藏是答案,它似乎是一种复杂的方式来获得正确;-)。第一步应该是
git stash save--keep index
,我想我必须在第4步删除它之前应用第一个stash。无论如何,这种方法对我不起作用,因为如果我有两个藏书,并尝试应用其中一个,它们都会被应用unexplainable@VonC不客气。:-)我真的觉得这种方法在建议的答案中是最直观的,所以我想帮助其他可能遇到它的人,使其更容易成功地应用。这也将帮助我有一个很好的参考,我一定会谷歌我的方式再次稍后(6个月后,当我需要再次,并忘记了确切的步骤)@怀特瑞德:开放性问题:你在理解什么方面有困难?重置、重设基础和提交的手册页应该详细描述我使用的所有选项,我使用的步骤应该是一步一步的逻辑操作?也是一个有趣的解决方案+1.出于好奇,您是否重新尝试了我的
git stash
答案的更新版本?是的,我已经重新尝试过,它工作正常,除非有一些新的(以前未跟踪的)文件。我的带有补丁的变体在这种情况下也会失败。谢谢你的回答!这启发我制作了一个更好的、可编写脚本的版本,并制作了另一个只能保存阶段性更改的脚本。(注意,在git清理过程中,这可能会从工作副本中删除一些空的子目录。鉴于git通常不考虑空目录,这可能很难避免。)为什么使用“差异树|应用;添加-A“而不是”签出$INDEXTREE--。"? 请注意,使用树签出不会更改您的分支,因此这两个分支应具有相同的净效果,但签出速度应更快,因为它不必构建和解析修补程序文件,然后重新扫描工作树以回填索引。对于第一个差异树,您需要保存的INDEXTREE和所有树之间的更改。你也不想随便看看。对于第二种情况,使用git checkout将INDEXTREE中的更改添加到索引中,但它们应该是unstaged@WalterMundt不过谢谢你看一看。当时我还没有考虑过git checkout,而且我总是乐于接受建议:)看起来checkout可以为未老化的ch工作
#!/bin/sh

# first, go to the root of the git repo
pushd `git rev-parse --show-toplevel`

# write out a tree with only the stuff in staging
INDEXTREE=`git write-tree`

# now write out a tree with everything
git add -A
ALL=`git write-tree`

# get back to a clean state with no changes, staged or otherwise
git reset -q --hard
git clean -fd

# apply the changes that were originally staged, that we want to
# be unstaged
git checkout $INDEXTREE -- .
git reset

# apply the originally unstaged changes to the index
git diff-tree -p $INDEXTREE $ALL | git apply --index --reject

# return to the original folder
popd