强制推送 Git 中的个人分支是否安全?

7

假设我正在一个名为feature的个人分支上工作。

  1. 我进行了5次提交。
  2. 我在主分支上进行了变基。
  3. 我将我的分支推送到远程分支。
  4. 我用git reset --hard回到了第3次提交。
  5. 我从主分支合并了代码。
  6. 我推送到远程分支(必须使用-f)。

这样做是否安全,会对主分支造成任何问题?最终我需要将feature合并到master中。


只要你不碰 master 分支,就安全了。抱歉,我不知怎么想到你重写了主分支。 - raina77ow
@raina77ow 但是当我将主分支与我的分支合并(在强制推送后),这会影响到什么吗?因为我之前已经强制推送了我的分支。 - user3214546
合并分支不会重写其历史记录。顺便问一下,没有与主分支合并是通过快进进行的吗? - raina77ow
@raina77ow 是的,它是ff,但我不确定。有时在将我的分支与主分支合并后,我会压缩提交,然后再次与主分支合并。我很困惑这是否会重写主分支。 - user3214546
1个回答

11

只要确实是私有的,并且只推送到私有分支,你就足够安全;原因在于:

分支是一种特定类型的“引用”,提供了提交的ID。

当你推送或拉取时,你要求git使用你的存储库与另一个git和另一个存储库通信。使用fetch,你要求你的git请求他们的git为你的git提供你还没有的东西,然后你的git为你的存储库设置“远程分支”,标识新带来的内容。使用push,你要求你的git发送一些提交,然后要求他们的git将它们的引用指向(其中的一些)这些提交。

当你“强制推送”时,你让你的git告诉他们的git设置这些引用,即使这可能会“丢失”提交(如git reset)。

请记住,在git中,提交形成一个图形("有向无环" 图形或DAG),以使提交可达,需要使用引用

A <- B <- C

每个大写字母代表一个提交记录。每个提交都有一个不同的“真名”SHA-1(40个字符的外观类似于1fc3e7aa...)。给定其中一个这样的大而丑陋的SHA-1名称,例如提交C的真名,您(或git)读取提交并查找“父”提交,在本例中为提交B的另一个大而丑陋的SHA-1。然后您阅读该提交并找到提交A的大而丑陋的SHA-1。

但是您从哪里获取提交C的大而丑陋的SHA-1?您可以尝试记忆它,但那似乎是一个糟糕的计划。相反,为什么不创建一个小文件,比如.git/refs/heads/feature,并将大而丑陋的SHA-1写入该文件呢?更好的是,让 git 这样做如何?

这就是引用的含义 - 在本例中,分支名称:在 refs / heads / 类别下的名称。

现在,您只需要记住名称 feature 即可。此外,git可以查看 refs / 目录并找到所有您的引用:分支(在 refs / heads / 中),标签(在 refs / tags / 中),注释(在 refs / notes / 中)等。

任何具有指向其的名称的提交记录都是“可达”的:您(或git)打开名称,读取SHA-1,然后获取提交。但是,任何以这种方式间接找到的提交记录也都是可达的:也就是说,只要我们能够直接找到C,我们就可以使用它来找到B,然后使用该提交找到A

当您执行 git reset 时,您正在告诉您的git移动一个引用。让我们将该序列扩展一些以添加一个新的提交D,并使 feature 指向D

A <- B <- C <- D   <-- feature

现在让我们执行 git reset --hard 命令回到提交 C。虽然无法使用纯文本将 D 淡化,但我会将其推开:

              D
            /
A <- B <- C   <-- feature
我们已经告诉 Git 把 feature 移动到指向 C,那么又有什么东西指向 D 呢?没有什么——或者说是 "几乎没有什么":Git 有 "reflog",并且有 reflog 条目保留了 D 另外30天(默认情况下)。但是对于正常的目的而言,提交 D 已经不存在了。至少,它不再 容易地 联系到,git log 默认情况下也不会显示它。一旦它真正不可达(没有更多的 reflog 条目),Git 就会最终进行“垃圾回收”,并将其从仓库中删除。
如果现在要求 git push 通知其他 Git 将某个其他存储库的 feature 指向提交 C,那么也将从那里丢失提交 D(当然,假设他们起初就有 D)。
问题特别严重的是,当某些人使用这个相同的“其他”(共享的)Git 存储库,并且依赖于提交 D 时。在某些时候,他将调用这个共享存储库,并询问 feature 中有什么内容,然后回复说 "分支 feature 指向提交 C" ,然后他将不得不想办法没有提交 D,或重新提供提交 D,等等。
你说没有人使用这个分支(它是私有的),因此没有人依赖于提交 D
还有一件事需要知道,尽管你的 reflogs 可以让你在30天内恢复提交 D,但是你可以推送到的存储库通常会禁用 reflogs。这意味着,一旦你使提交 D 在服务器上不可达,它就有可能被垃圾回收。
最后,如果你开始养成强制推送的习惯,请非常小心你所强制推送的内容,否则可能会意外地强制删除其他人正在使用/依赖的提交。

真正优秀的回答。感谢详细的解释。+1 - Keith Pinson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接