假设我正在一个名为feature
的个人分支上工作。
- 我进行了5次提交。
- 我在主分支上进行了变基。
- 我将我的分支推送到远程分支。
- 我用
git reset --hard
回到了第3次提交。 - 我从主分支合并了代码。
- 我推送到远程分支(必须使用
-f
)。
这样做是否安全,会对主分支造成任何问题?最终我需要将feature
合并到master
中。
假设我正在一个名为feature
的个人分支上工作。
git reset --hard
回到了第3次提交。-f
)。这样做是否安全,会对主分支造成任何问题?最终我需要将feature
合并到master
中。
只要确实是私有的,并且只推送到私有分支,你就足够安全;原因在于:
分支是一种特定类型的“引用”,提供了提交的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
)。D
时。在某些时候,他将调用这个共享存储库,并询问 feature
中有什么内容,然后回复说 "分支 feature
指向提交 C
" ,然后他将不得不想办法没有提交 D
,或重新提供提交 D
,等等。D
。D
,但是你可以推送到的存储库通常会禁用 reflogs。这意味着,一旦你使提交 D
在服务器上不可达,它就有可能被垃圾回收。
master
分支,就安全了。抱歉,我不知怎么想到你重写了主分支。 - raina77ow