繁体   English   中英

git commit删除整个目录

[英]git commit deleted whole directory

用户将单个文件更改为git后,一堆他们没有碰到的目录被删除。 怎么样?

这是最后2次提交

git log -10
3dc0de9 - change
ddc0fe6 - change
...

最上面的提交3dc0de9是删除目录的那个,但是它只更改一个文件

git show --name-only  3dc0de9
(1 file updated)

但是,还删除了31个其他文件,包括7个整个子目录!

git diff --name-only ddc0fe6..3dc0de9
(31 files deleted)

如果我git cherry-pick 3dc0de9 ,我只会得到我期望的单文件更改,但我真的很想知道这是如何发生的以及如何避免意外删除

奇怪...这个差异显示正确的事情

git diff --name-only 3dc0de9~1..3dc0de9
(1 file updated)

git log (带有或不--graph )必须一次提交一次提交,因此它必须使图线性化。 这样,它将对提交进行排序 默认的排序顺序是按提交时间戳记排序的,但是这里有些微妙之处是我一开始就感到困惑(我认为没有正确记录): 默认情况下,您将看到按提交顺序而不是时间戳记提交的内容。订单,除非您达成合并。 在您的情况下,合并就在顶部,这导致了混乱。 由于多种原因,使用--graph帮助

另外:上面的“提交顺序”是指Git链接提交的方式。 您添加的每个新提交都会记住其父级,因此在只有三个提交的新存储库中,它们看起来像这样:

A <-B <-C   <--master

我们说分支名称master 指向提交C因为此刻它包含C的哈希ID。 提交C点以提交B的方式相同( BC父级) ,提交B点以提交A 因为A是第一个提交,所以它根本没有指向:这是一个根提交 它没有父母! 所以“提交顺序”是C然后B然后A 要将新的提交D添加到master ,Git会以C作为D的父代写出提交D ,然后更改名称master ,使其现在指向D

A <-B <-C <-D   <--master

这里没有任何排序:Git只是从D开始,使用其向后指针查找C ,依此类推。

请注意,每个提交(一旦完成)都是完全只读的:提交中的父链接会及时冻结,就像其他所有有关该提交的内容一样。 实际上只有分支名称 (在这种情况下为master )会更改! 新提交会在您添加它们时显示; 它们指向未更改的现有提交; 并且您的分支名称始终指向链中的最后一个提交。 因此,Git必须向后工作,从最后一个开始到第一个工作。

当您没有分支和合并时,这很容易。 合并时比较困难:

...--E--G--...---M--N   <-- master
      \         /
       F--...--L   <-- feature

Git可以从N开始并回到M ,但是M两个父母而不是一个。 现在Git有显示父母双方的一个 第一

排序方式

这是有关排序的棘手问题:Git实际上是从优先级队列发出提交的。 正是这个优先级队列实现了排序。 优先级队列的初始内容是在命令行上明确命名的所有提交:

git log --option --another abcd123 --more f0bc3a1 --etc HEAD

命名三个起点: abcd123f0bc3a1HEAD (无论提交解析为f0bc3a1提交哈希ID-大概不是其他两个之一,否则只有两个起点)。

如果省略所有起点,则git log插入HEAD ,根据定义,该HEAD命名为一次提交。 例如,如果将HEAD附加到mastermaster点上以提交N ,则git log将从N开始。

由于优先级队列具有优先级,因此队列中出来的第一个元素将确定首先显示哪个提交。 默认是按照提交时间戳顺序插入这些提交。 使用各种排序选项可以更改将提交插入队列的顺序。

实际上, 显示提交会将所有该提交的父级插入队列。 因此,当git log显示合并时,它将所有合并的父提交按优先级顺序插入队列。

由于默认的git log仅在队列中进行一次提交,因此它首先显示HEAD 只要不是合并,它就只有一个父对象,因此队列的长度保持为1,其中只有HEAD (单个)父对象。 这种git log显示每次提交一次, 而不管提交时间戳如何 只有当我们达到合并提交(如您的00d4f68 )时,我们00d4f68遇到问题。

00d4f68 ,Git将父母双方都插入了队列: ddc0fe63dc0de9 这意味着它现在可以选择接下来要显示的提交,并且默认情况下,它按提交时间戳进行排序。 提交时间戳由进行提交的人设置。 如果不同的人在不同的计算机上进行不同的提交,并且其中一台计算机的时间设置不正确,您将获得一些奇怪的时间戳记,从而得到一些奇怪的排序。

使用- --graph

使用--graphgit log还可以显示图形(有点粗略的ASCII艺术)。 这具有强制进行拓扑排序的副作用:在显示特定父提交之前,先显示某个父的所有子。 默认值为--topo-order--date-order--date-order --author-date-order也是拓扑排序,应在此处允许。 (文档中提到--date-order 允许的,但两者都应该是 。)

请注意,您可以自己使用--topo-order (不使用--graph )来进行相同的拓扑排序。 但是,如果没有--graph ,您将无法确定何时停止提交一条--graph ,何时停止另一条提交,即,合并的两条腿分别在哪里,或者它们又回到何处。

为了使图形更容易理解,请使用--oneline 要查看哪些提交也具有哪些分支和标记标签,请添加--decorate或设置log.decorate

--decorate --oneline --graph的组合非常有用,并且容易记住,因为它拼写为“ DOG”。 :-)

您还可以添加--all以从所有引用(所有分支和标签,如果有的话添加存储,再加上其他提交引用)开始,其拼写为“ A DOG”。

啊哈! 看起来像是来自一个非常老的分支的合并,以某种方式重置了这些文件。 令人讨厌的提交38bbeb1来自一个更老的分支,但被放置在git log之上。

git log --graph 3dc0de9~3..master
*   00d4f68 - (origin/master, origin/HEAD, master) Merge branch 'master'
|\  
| * ddc0fe6 - change
| * ...snipped out 51 commits on this branch...
| * db0e306 - change
* | 3dc0de9 - change
|/  
* 38bbeb1 - change
* 5b103f6 - change

现在真正的问题是如何在将来避免这种情况。 我通常会执行git fetch和rebase操作,但是我不确定TortoiseGit中的操作步骤

我通过重新设置为最后一个良好的提交来使事情“正确”,然后挑选“不好的”提交:

git reset --hard ddc0fe6
git cherry-pick 3dc0de9

无需删除文件即可进行所有正确的更改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM