如何忽略`git stash -p`中添加的块 [英] How to ignore added hunks in `git stash -p`

查看:59
本文介绍了如何忽略`git stash -p`中添加的块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下这种情况:

 #编辑两个文件git add -p//从一个文件添加块 

现在,当您运行 git stash -p 时,它将再次询问您是否要存储刚刚通过 git add -p 选择的块.有没有什么方法可以配置git来默认忽略这些已经添加的块呢?大多数时候,我不想隐藏我已经添加的内容.

解决方案

好吧,从注释中,我们需要的是尚未添加的所有所有更改的存储(是否在 git add -p ,或尚未添加).

这样做的原因是在提交状态之前,对过渡状态应用了一些测试/潜在的调整.

这是一个直接的 git stash -k ,它像往常一样存储所有内容,但保留索引状态和相应的工作树,即从工作树中清除所有我不想提交的内容.

所以:

  git stash -kgit clang格式git提交 

,该存储库现在具有四个有趣的快照:原始内容(也称为存储库),快照索引,快照工作树以及当前索引(,提交和工作树),即 stash ^ 2处的索引快照并应用清理.请注意,这里的所有三个新快照(也称为提交)都将存储库作为父级.

现在,您希望您的工作树变回原来的位置,但是很明显,从基索引到隐存索引和工作树的更改与当前索引和工作树中的更改不匹配(并且所有新提交都匹配),因此当git转到弹出存储库会发现冲突:从存储库基础到存储索引的更改与从存储库基础到当前索引的更改不匹配.

如果Git直接提供了您想要的东西,则将所有工作树都存储在索引中,除了 会发生变化",您可以使用它,然后存储弹出不会有任何麻烦,直接使用 git stash pop 即可.幸运的是,如果Git在任何方面都擅长,那就是合并,合并,分裂和一般性的差异消除.

  git cherry-pick -nm2隐藏#cherry-pick也更新了索引.也许git reset在这里可以撤消这些东西.git藏起来 

Stash Pop是从Stash Base到St藏身状态的更改与从Stash Base(通常非常类似于当前Base)到当前状态的更改的合并.您希望隐匿的工作树在您的工作树中变回原来的样子,但是只有您尚未添加的那些,因为您已经添加的那些都仍在这里,它们现在略有不同./p>

所以cherry-pick是 -n ,没有提交, -m2 ,更改的主线是它的第二父级,即您所做但未添加的所有差异藏起来的时候.

一个示例可能会有所帮助,

  cd`mktemp -d`git initprintf>文件%s \\ n 1 2 3 4 5git添加.; git commit -m1printf>文件%s \\ n 1 2a 3 4 5git添加printf>文件%s \\ n 1 2a 3 4a 5 

现在您已经有效地 git add -p 进行了2a更改,而4a更改仅在您的工作树中.

  $ git stash -k$猫文件1个2a345$ sed -i'2s,^,_,'文件#缩进2a行$ git commit -am2 

现在,初始提交:/1 1 2 3 4 5 ,您当前的提交,索引和工作树都是 1 _2a 3 45 ,保存的索引为 1 2a 3 4 5 ,保存的工作树为 1 2a 3 4a 5 .

您要返回的更改是隐藏的索引和隐藏的工作树之间的差异,这是隐藏提交与第二个父提交之间的差异.因此,那个樱桃采摘.


包括拼写摘樱桃"的其他方式

  git cherry-pick -nm1 -Xours隐藏 

应用所有隐藏的工作树更改,但在发生冲突的情况下采用本地版本(基本上是查找并丢弃冲突的差异,而不是像 -m2 那样避免它们)和

  git diff stash ^ 2..stash | git apply -3 


让自己更容易做的是编写脚本区域,谈论设置最简单的方法是使用git别名,

  git config --global alias.poptree'!git cherry-pick -nm2隐藏;git reset;git stash pop' 

,您现在有了 git poptree 命令来执行所需的操作.


edit:作为进一步的尝试,假设您在记住已隐藏的工作树更改之前继续进行了更多工作,cherry-pick将正确更新工作树和索引,但是重设将撤消您已添加的所有更改到新索引.现在您处于核心指挥领域,

 (index =`git write-tree`&&git cherry-pick -nm2隐藏git读取树$ index&&git藏起来) 

这是我如何真正实现此目的.

Imagine this scenario:

# edit two files
git add -p // add hunks from one file

Now when you run git stash -p, it will again ask you whether you want to stash the hunks that you just selected via git add -p. Is there some way to configure git to ignore these already-added hunks by default? Most of the time, I don't want to stash stuff that I added already.

解决方案

Okay, from comments, what's wanted is a stash of all changes that haven't already been added (whether excluded during a git add -p, or just not added yet).

The reason for this is to apply some tests/potential tweaks to the staged state, before committing it.

That's a straight git stash -k, stash everything as usual but keep the indexed state and the corresponding worktree around, i.e. clean from the worktree everything I'm not about to commit.

So:

git stash -k
git clang-format
git commit

and the repository now has four interesting snapshots: the original content aka stash base, the snapshotted index, the snapshotted worktree, and the current index(, commit, and worktree) which is the index snapshot at stash^2 with the cleanups applied. Note that all three of the new snapshots aka commits here have the stash base as parent.

Now you want your worktree changes back, but clearly the changes from the base to the stashed index and worktree do not match the ones in the current index and worktree (and new commit, those all match), so when git goes to pop the stash it will find conflicts: changes from the stashed base to the stashed index do not match the changes from the stash base to the current index.

If Git offered what you want directly, a "stash all the worktree changes except the ones in the index", you could have used that and then the stash pop wouldn't have any trouble, a straight git stash pop would do it. Fortunately, if Git's good at anything, it's merging, combining, splitting, and general all-around munging of differences.

git cherry-pick -nm2 stash
# cherry-pick updated the index, too. maybe git reset here to unstage that stuff.
git stash drop

Stash pop is a merge of the changes from the stash base to the stashed state with the changes from the stash base (which is usually remarkably similar to the current base) to the current state. You want the stashed worktree changes back in your worktree, but only the ones you hadn't already added, since the ones you had added are all still here, they're just a little different now.

So the cherry-pick is -n, no commit, -m2, mainline for changes is its second parent, i.e. all the differences you had made but not added when stashing.

An example might help,

 cd `mktemp -d`
 git init
 printf >file %s\\n 1 2 3 4 5
 git add .;git commit -m1
 printf >file %s\\n 1 2a 3 4 5
 git add .
 printf >file %s\\n 1 2a 3 4a 5

now you've effectively git add -p'd the 2a change, and the 4a change is only in your worktree.

 $ git stash -k
 $ cat file
 1
 2a
 3
 4
 5
 $ sed -i '2s,^,_,' file   # indent the 2a line
 $ git commit -am2

Now, the initial commit, :/1, is 1 2 3 4 5, your current commit, index and worktree are all 1 _2a 3 4 5, your stashed index is 1 2a 3 4 5 and your stashed worktree is 1 2a 3 4a 5.

The changes you want back are the difference between your stashed index and your stashed worktree, that's the stash commit's differences from its second parent. Hence, that cherry-pick.


Alternate ways of spelling the cherry-pick include

git cherry-pick -nm1 -Xours stash

which applies all the stashed worktree changes but takes the local version in case of conflict (basically it's finding and throwing away the conflicting differences instead of just avoiding them as the -m2 does) and

git diff stash^2..stash|git apply -3


Making all this more easy on yourself is scripting territory, the easiest way to talk about setting it up is as a git alias,

git config --global alias.poptree '!git cherry-pick -nm2 stash; git reset; git stash pop'

and you now have a git poptree command to do what you want.


edit: as a further fillip, suppose you had gone ahead and done some more work before remembering your stashed worktree changes, the cherry-pick will correctly update the worktree and index but the reset will back out any changes you had already added to the new index. Now you're in core-command territory,

( index=`git write-tree` &&
  git cherry-pick -nm2 stash &&
  git read-tree $index &&
  git stash drop
)

is how I'd implement this for real.

这篇关于如何忽略`git stash -p`中添加的块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆