Git: 如何检查是否有任何提交被删除?

Git: How to check if any commits were deleted?

我想确保 fetch 没有从我的本地存储库中删除(或压缩)远程存储库中的任何提交。

我还需要告诉我,是否有任何提交在远程存储库中被删除(或压缩)。

如何确保我的 fetchpull 不会删除任何提交(在我的本地 PC 上)?

另一个相关问题:如何使Git删除与删除的远程提交对应的本地提交?

这个问题有一些问题,也许这就是它得到 down-voted 的原因,但我们可以 从中得到一些东西。

让我们看一下 Git 存储库中实际存储的内容,绘制为图表,在 git fetch 之前和之后,看看我的意思。

我们将从这里开始:

          A   <-- master
         /
...--o--*   <-- origin/master
         \
          B--C   <-- origin/dev

在这里,在本地存储库中,在 运行ning git fetch origin 之前,我们有:

  • 一些共享提交,从提交 * 开始并向后工作;
  • 一个提交是"ours",提交A,在我们的master,不在origin/master
  • 上游唯一的两个提交,在他们的 dev 上,这是我们的 origin/dev:提交 BC

现在我们 运行 git fetch,打印一些输出,由于某些原因我们没有看到或忘记了。然后我们再次仔细检查我们的图表并发现:

          A   <-- master
         /
...--o--*--D   <-- origin/master
            \
             E   <-- origin/dev

也就是说,我标记为 BC 的两个提交根本无法从任何 origin/* 名称访问,而新提交 DE 出现了。名称 origin/master,这是我们 Git 对他们 master 的记忆,现在标识提交 D,而名称 origin/dev 标识提交 E.

很有可能——但无法从这个健忘症患者的观点中确定——提交 D 是压缩提交 BC 以及可能的一些额外提交的结果我们从未有过。 Commit E 可能是全新的。另一方面,我们只是不知道。

不过,我们可能拥有比这更多的信息。特别是,如果我们启用了 reflogs,我们将有 origin/master@{1}origin/dev@{1}。这些将分别指向提交 *C,我们将通过 origin/master@{1} reflog 保留 CB

我们可能还有不同的起始图片。例如,也许我们的起始图像看起来像这样:

          A   <-- master
         /
...--o--*   <-- origin/master
         \
          B--C   <-- dev, origin/dev

在这种情况下,我们的结局图片如下所示:

          A   <-- master
         /
...--o--*--D   <-- origin/master
         \  \
          \  E   <-- origin/dev
           \
            B--C   <-- dev

须知

这里有几点需要注意:

  1. 我们永远不会丢失我们自己的分支名称指向的任何提交。
  2. 我们从不更新我们自己的任何分支名称。
  3. 我们会更新我们的 remote-tracking 名称,但是当我们这样做时,如果启用了引用日志,它们的 previous 值将保存在我们的引用日志中。

因此:

I want to ensure that no commits are deleted (or squashed) from my local repository by fetch from a remote repository.

如果 "no commits" 你的意思是 "no commits to which I have names other than remote-tracking names",这就是自动正确的。

Also I need to reveal to me, if any commits were deleted (or squashed) at the remote repository.

在这里,您可以查看任何已更新的 remote-tracking 名称之间的区别——请注意,git fetch 告诉您它正在更新哪些名称——以及它们保存的 reflog 值。例如,如果更新了 origin/masterorigin/dev,您可以将 origin/master@{1}origin/master 进行比较。

至此,几个特殊的syntaxes described in the gitrevisions documentation就变得相当得心应手了。特别是 two-dot 和 three-dot set-difference 和 symmetric-difference 运算符告诉我们我们想知道的:

git rev-list origin/master@{1}..origin/master

生成提交列表 添加到 origin/master 和:

git rev-list origin/master..origin/master@{1}

生成 origin/master 中删除的提交列表。我们的存储库中仍然有所有这些提交,因为引用日志名称指向它们;在 reflog 条目过期之前它们不会消失。

我们可以使用 three-dot 语法和 --left-right 或类似的实体来枚举和识别添加和删除的提交,标记它们在哪个 "side" 对称差异上:

git rev-list --left-right origin/master@{1}...origin/master

使用所有这些信息,如果我们真的关心的话,我们可以自动猜测哪些提交可能是其他提交的变基或压缩,但在某些情况下这是注定要失败的努力(例如,解决合并冲突)。

Another related question: How to make Git to delete local commits corresponding to deleted remote commits?

这比较棘手,因为它取决于您的意思。但是,如果您的意思是我猜您的意思,那么 git rebase--fork-point 操作实际上就是为了处理这个问题而设计的。 fork-point 代码使用了上游分支的reflog。有关详细信息,请参阅