如何还原已提交的行以成为未分级的更改

时间:2017-10-16 19:00:17

标签: git github atlassian-sourcetree

比我承认的更常见,我会投入一些我不打算做的线/帅哥。我想要撤消。

但是让我们理解我不打算提交的撤消更改意味着什么。这并不意味着删除更改。从字面上撤消提交的行更改意味着存在删除它们的提交,但更改将保留为“未暂存”。

请不要建议重置头,因为这不能完成撤消“某些行/帅哥”(但不是其他行)的具体任务。理解我希望在这里做的事情比这更复杂,因为它涉及一个恢复一组特定更改的提交(但不是该提交中的所有更改),然后重做这些更改,但是作为未分阶段。 / p>

我怀疑我是唯一一个曾经想要这样做的人。

在git中有一个相当简单的方法吗?在SourceTree中怎么样?

3 个答案:

答案 0 :(得分:2)

TL; DR

您可能重置,可能使用--soft,然后使用git checkout -p,然后使用git commit。这通常是最简单和最简单的。但你不能 这样做。

接下来是一个很长的解释(带有一些图形图片)。

为什么每个人都会告诉您git reset

一旦你进行了一些提交,它们就会永久存储在那个提交中。让我们备份很多,因为Git并没有像许多人认为的那样存储文件。

例如,考虑这个微小的存储库只需要三次提交。他们的实际ID是一些难以理解的哈希字符串;为简单起见,我将A标记为C而不是:

A <-B <-C   <-- master

名称master包含提交C的哈希ID。提交C包含其父提交{1}的哈希ID,提交B包含其父提交B的哈希ID。由于A是第一次提交( root 提交),因此它没有父级,并且Git将在显示提交A后停止遍历历史记录。

我们还说A 指向 masterC指向C,依此类推。

这三个提交中的每个提交都是您的来源的一系列快照

进行提交只是意味着提交指向B的提交D,然后将名称C更改为指向{{1 }}:

master

这个新提交是永久性的,不可更改的。

现在,每个提交 是整个源的完整独立快照。提交D的每个文件都与您运行A <-B <-C <-D <-- master 时的(暂存)表单完全相同。提交D还包含完全(暂存)形式的每个文件,当您或任何人运行创建git commit的{​​{1}}时。要将C视为更改(来自git commit),Git必须提取所有C,然后提取所有D,然后比较两者看看有什么不同。

同样适用于您的临时区域和工作树中的内容,除了这些是可塑的(非永久性的)这一事实。也就是说,索引/暂存区域包含建议的提交,工作树包含您可以实际处理的文件(因此名称&#34;工作树&#34;)。 / p>

当Git告诉您已经进行了阶段性更改时,Git正在做的是比较索引/暂存区域中的内容与当前提交中的内容,例如commit C 。无论有什么不同,Git都会呈现出一个阶段化的变化&#34;。

当Git告诉您有 un 阶段的更改时,Git正在做的是将工作树中的内容与索引/分段中的内容进行比较 - 区域。无论有什么不同,Git都表现为&#34;未分阶段的变化&#34;。

现在,让我们说你做了C - 你原来的问题暗示你已经做了这个 - 但你有更多的东西上演 - 即,当时复制到索引/登台区域比你想要的还要多。 D中的永久存储文件集包含您不想要的表单。

此时,index / staging-area与运行D时相比没有变化。那么,提交D中的内容(确切地)匹配索引/登台区域中的内容,这意味着没有任何内容可以进行提交。

由于工作树是它自己独立的实体,现在工作树中的内容仍然是D之前的内容,所以未暂存的更改仍未解除。但是&#34;上演的变化&#34;已经成为一个完整的快照。

这意味着您需要摆脱提交git commit以及D所在的位置。如果您以某种方式执行此操作更改< em>没有别的,所以名称D指向提交D,我们得到这个图:

git reset

Git现在会将master中的内容与您的索引/登台区域中的内容进行比较,并向您展示&#34;暂停提交&#34;。实际上,它会在你创建C之前显示为暂停的,恰好是它所显示的内容,因为&#34;索引中的所有内容&#34; (建议的下一次提交)就是 时你所做的 D [abandoned] / A--B--C <-- master

你真的想摆脱这个提交

由于提交不可更改,如果您保留C并添加更多提交,则在您的存储库历史记录中,您将拥有此不需要的快照。所以你必须丢弃它 - 但你不一定要用D来做这件事。但是,如果你这样做,可能更容易

(我说的每个地方&#34;必须&#34;,它当然是可选的。如果你愿意,你可以保留无用/坏/负值D提交。但我怀疑你不打算。)

更改已暂存的

现在让我们看一下 un 上演的一些变化。

假设您执行此重置,实际上是Dgit reset。这告诉Git将D向后移动一步,而不触及索引/暂存区域,并且不触及工作树。现在,您可以git reset --soft HEAD^使用git reset --soft HEAD~1。这将允许您对索引中的文件副本进行小的更改。

如果您没有执行master,您仍然可以运行git checkout -p -- <path>,但是您想要添加提交的哈希ID { {1}},或者某种方式告诉Git查看提交git reset。这可能就像git checkout -p一样简单。

如果您执行这些C命令之一(包含或不包含初始C),您可以在索引中获取该文件的副本以获得所需的表单。但是,很难告诉 它是否具有您想要的格式,因为无法查看索引中的文件版本

查看索引中的内容

要查看索引中的内容,通常会运行git checkout -p HEAD^ <path>(将git checkout -p与index / staging-area进行比较)或git reset --soft(以便将索引与工作进行比较) -树)。这并没有直接显示内容;相反,它会向您显示这些内容的内容有何不同<{1}} - 您可能知道的内容 - 或者来自工作树的内容,您可以见。

这些再次是&#34;阶段性变化&#34; (索引的内容与git diff --cached提交的内容相比),或者&#34;未分级的更改&#34; (与内容索引相比的工作树的内容)。但他们与HEAD提交相关。如果尚未运行git diff,则必须注意添加&#34;提交HEADHEAD D {{1} D` vs index&#34;。

所以这就是为什么你真的想要从HEAD开始。

git reset的默认值为C

如果您运行commit,而没有" to any changes shown as "commit,Git将消灭(重置)您当前的索引/暂存区域,将其替换为以前的内容提交。

Git不会触及工作树,所以如果您已经从工作树中仔细构建了索引,那么现在可以重新完成所有工作。但如果这是很多工作,你可能想要git reset --soft重置。

不过,这是一个选项,如果你不小心(或在绝望中)运行git reset或默认--mixed,还有一些有用的东西。

安排索引后,您可以提交

一旦你按照你想要的方式设置了索引/暂存区,现在就可以进行你想要的提交。

如果你已经提交了git reset HEAD^,那么提交图是:

--soft

您可以运行--mixed而不是常规--mixed。这样做是为了让你的新提交git reset,并以正常的方式指向D - 除了一件事:新的提交A--B--C--D <-- master 将作为其父级,提交git commit --amend。这会将git commit推到一边并放弃它:

E

但如果你之前master做了E或默认C - 那么你已经提交D推到了那边和被遗弃的,所以你可以用通常的方式添加提交 D [abandoned] / A--B--C--E <-- master

答案 1 :(得分:1)

我很确定您正在寻找-p source code让您

  

<tree-ish>(或索引,如果未指定)与工作树之间的差异交互式选择帅哥

答案 2 :(得分:0)

可行解决方案:反向猛烈

小心 SourceTree GitKraken 反向大块错误...如果你试图反转大块,他们就会有整个文件被反转的错误。我看到GitKraken在2017年10月9日用版本3.1.1修补了它。但我不知道SourceTree的状态。