[英]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
的方式相同( B
是C
的父级) ,提交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
命名三个起点: abcd123
, f0bc3a1
和HEAD
(无论提交解析为f0bc3a1
提交哈希ID-大概不是其他两个之一,否则只有两个起点)。
如果省略所有起点,则git log
插入HEAD
,根据定义,该HEAD
命名为一次提交。 例如,如果将HEAD
附加到master
和master
点上以提交N
,则git log
将从N
开始。
由于优先级队列具有优先级,因此从队列中出来的第一个元素将确定首先显示哪个提交。 默认是按照提交时间戳顺序插入这些提交。 使用各种排序选项可以更改将提交插入队列的顺序。
实际上, 显示提交会将所有该提交的父级插入队列。 因此,当git log
显示合并时,它将所有合并的父提交按优先级顺序插入队列。
由于默认的git log
仅在队列中进行一次提交,因此它首先显示HEAD
。 只要不是合并,它就只有一个父对象,因此队列的长度保持为1,其中只有HEAD
(单个)父对象。 这种git log
显示每次提交一次, 而不管提交时间戳如何 。 只有当我们达到合并提交(如您的00d4f68
)时,我们00d4f68
遇到问题。
在00d4f68
,Git将父母双方都插入了队列: ddc0fe6
和3dc0de9
。 这意味着它现在可以选择接下来要显示的提交,并且默认情况下,它按提交时间戳进行排序。 提交时间戳由进行提交的人设置。 如果不同的人在不同的计算机上进行不同的提交,并且其中一台计算机的时间设置不正确,您将获得一些奇怪的时间戳记,从而得到一些奇怪的排序。
--graph
使用--graph
, git 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.