9

我只是出于好奇才问这个。现实生活中这种情况还有其他的处理方式,但是我觉得git下面的行为有点奇怪。

摘要:隐藏在幕后创建了两个提交,一个包含索引,另一个包含未添加的编辑。如果我们检查后者并尝试对其进行变基,我们不知何故只能从索引中获取更改。这是为什么?

详细示例如下:

首先让我们使用一次提交创建一个 repo,然后再添加一次编辑到索引,然后再进行一次未添加到索引的编辑,然后存储:

git init
echo 1 > a.txt
git add a.txt
git commit -m"First commit"
echo 2 >> a.txt
git add a.txt
echo 3 >> a.txt
git stash
git log --all --graph --oneline

  *   5c00fc0 WIP on master: c8af537 First commit
  |\  
  | * 965c986 index on master: c8af537 First commit
  |/  
  * c8af537 First commit

因此,git stash似乎将索引和未添加的编辑都保存为具有自己哈希值的提交(在我的情况下,索引为 965c986,未添加的编辑为 5c00fc0)。

现在编辑一个新文件并提交:

echo x >> b.txt
git add b.txt
git commit -m"Second commit"

所以所有的提交现在看起来像:

git log --all --graph --oneline

  * b589f50 Second commit
  | *   5c00fc0 WIP on master: c8af537 First commit
  | |\  
  |/ /  
  | * 965c986 index on master: c8af537 First commit
  |/  
  * c8af537 First commit

比如说,我们现在想要获取隐藏的编辑并将它们与第二次提交结合起来。还有其他方法可以做到这一点(例如git stash apply,但是如果我们已经清理了存储,然后从 reflog 中挖掘了提交怎么办),但让我们尝试一下:

git checkout 5c00fc0
[warning message here]
cat a.txt
  1
  2
  3
git rebase master
  First, rewinding head to replay your work on top of it...
  Applying: index on master: c8af537 First commit

但是现在,生成的文件a.txt只是:

cat a.txt 
  1
  2

这是整个图表:

git log --all --graph --oneline
  * 5fc3ade index on master: c8af537 First commit
  * b589f50 Second commit
  | *   5c00fc0 WIP on master: c8af537 First commit
  | |\  
  |/ /  
  | * 965c986 index on master: c8af537 First commit
  |/  
  * c8af537 First commit

所以看起来,即使我们检查了提交 5c00fc0,rebase 也只应用了提交 965c986 的更改,即我们隐藏时索引中的编辑。但是 5c00fc0 中的任何内容都被忽略了。

问:为什么会这样?这种行为有一些合理的解释吗?或者这应该被认为是一个错误?

4

3 回答 3

1

事实证明,git 只是(默认情况下)在变基时忽略合并提交。并且 stash 创建 WIP 提交和索引提交,而 WIP 提交是一个合并,因为它同时具有索引提交和 c8af537 作为父项。

与这样的存储无关。

于 2013-07-26T00:52:26.000 回答
0

我今天早上在 GUI 应用程序中意外删除了一个存储后遇到了这个问题。起初我尝试像其他人一样进行变基,因为这是很自然的事情。然后我用duckduckgo搜索,找到了这个,但没有实际的解决方案。所以我更加努力地想出了这个:

假设我们有以下分支/引用:

  • dropStash指向具有所需内容的人工合并提交
  • parentOfStash指向此 ex-stash 分支的原始基本提交

然后我们可以简单地做:

  1. git checkout parentOfStash
  2. git cherry-pick -m 1 dropStash

其中 -m 1 告诉 git 将其中一个祖先视为主线。达达!享受 :-)

于 2014-12-07T23:19:31.040 回答
-1

对我的原始答案进行了大量编辑。

我对代码进行了一些深入研究并进行了一些自己的测试,然后发现了问题。当你在你的无头分支上做你的 rebase 时,你 rebase master。rebase 命令验证你正在变基的分支的头部,在这种情况下不包括存储。试试这个:

git checkout -b stashbranch 5c00fc0
git rebase stashbranch
git log --oneline --decorate --all

您应该会看到如下内容:

b589f50 (HEAD, refs/stash, stashbranch) Second commit

注意:如果您处于分离头状态但运行git rebase master它将根据我的测试将您的头设置为主头。您可以完成 git rebase 5c00fc0 并获得与分支相同的结果。

于 2013-07-25T07:08:54.153 回答