如果我从我的分支中删除文件,将从主中提取请求删除文件



也许这可能是菜鸟问题,但这困扰着我。任何帮助将不胜感激。

场景: 1] 克隆一个项目,其中包含一些文件,例如文件1,文件2,文件3

2] 创建一个新分支,比如分支1

3] 现在,如果我在我的分支中删除 file1 并进行一些其他更改,例如对 file2 并添加新的文件文件4

4] 执行拉取请求

问题:审阅者批准 PR 后,file1 会从主文件中删除吗?

文件首先不存在于分支中,1因此问题格式不正确。 但是,您可以自己测试这一点,正如博士在评论中建议的那样:

  • 在本地创建两个新的分支名称,例如test1test2;
  • 在其中一个新分支(test1),删除一些文件并提交;
  • 签出另一个分支并运行git merge --no-ff test1并观察结果。

下面是用于测试目的的命令序列;这假定要删除的测试文件test.ext。 根据需要进行更改。

git switch main
git branch test1 && git branch test2
git switch test1
git rm test.ext && git commit -m 'remove file for testing'
git switch test2
git merge --no-ff test1

该文件将从您的工作树中消失。 文件是否"在"分支test2? 我们所说的"分支test2"是什么意思?

如果我们避免使用有问题的单词分支,我们可以谈论提交。 Git 实际上是关于提交的。 文件存储在提交中(而不是分支中,分支相对不重要;只有提交对 Git 真正重要)。 像test1test2这样的分支名称仅用于查找特定的提交。 Git 通过原始哈希 ID 查找提交:那些像6cc022f7696a45f5b3814d7659a7b0f16436b4bf这样的丑陋的大字符串。 人类不擅长这些:他们看起来像随机的垃圾。 (它们根本不是随机的,但它们是故意随机的,不可预测。 它们对生物有毒;只有计算机才能消化它们并保持健康。2)

由于提交还用于提供哈希 ID 来查找其他(早期)提交 - 这就是 Git 存储库中历史记录的工作方式,因此"分支"有时意味着的一部分 - Git 能够在某个分支上找到最新的提交就足够了,在一个膨胀的 foop 中,它可以找到所有早期的提交,这些提交也"在"该分支上(使用"分支")。 像这里test1这样的分支名称使 Git 能够获取最新的提交:这就是名称的定义方式(这反过来又是"分支"有时含义的一部分)。

我们通过上述命令序列发现:

  • 文件test.ext确实存在于git switch main提取的提交中。
  • 文件test.extgit switch test1提取的提交中不存在
  • 文件test.ext也不存在于git switch test2提取的提交中。

由于 GitHub 通常会使用等效的git merge --no-ff进行 PR-merge3,这就是我们所做的提交,现在是分支test2的尖端。 因此,您可以看到删除文件将导致删除文件。

不过,这里真正关键的概念是:

  • 这些文件存储在提交中。
  • 提交已编号(按哈希 ID)。
  • 任何给定提交中存储的文件都是您(或任何人)提交时的样子,永远存在。

要使用提交,您可以使用git checkoutgit switchgit switch --detach或类似内容"检查出来"。 这会从该提交中提取文件。 因此,文件一旦提交,将永远存在。 它只是不一定在任何其他提交中。 如果它在五个提交中,它将永远在这五个提交中。 如果在第六次提交时将其删除,则它不在第六次提交中 - 永远! 未来的提交从以前的提交开始,所以未来提交的文件集也将缺少该文件,除非并且直到你把它放回去并提交它,然后它将在该提交中(永远)和将来的提交,除非并且直到有人更改或删除它。

每次提交都会永久保存每个文件。为了防止存储库变得臃肿和无法使用,存储在 Git 存储库中的提交中的文件是 (a)压缩和 (b)删除重复数据。 如果提交a123456中某个文件test.ext的内容与提交b987654中其他文件other.blargh的内容完全匹配,则该文件实际上只有一个副本(在本例中为两个不同的名称)。 Git 可以做到这一点,因为每个副本都是永久只读的:保存的test.ext没有更改的危险。 如果您创建一个具有不同内容test.ext的新提交c0ffee1,Git 会将该不同内容test.ext保存为一个新的不同文件(尽管使用相同的旧名称),稍后,git diff将显示名为test.ext的旧a123456文件和名为test.extc0ffee1文件之间的不同之处。

因此,即使是更简单的问题"删除文件是否将其从分支中删除"定义不明确,因为"分支"定义不明确。 删除文件会将其从一组提交中删除,从您进行的下一个提交开始。 每个提交都包含它包含的任何文件,以及它们拥有的任何内容,并且只要该提交存在,具有该内容的文件也存在

运行git merge组合工作,如果该工作包括"删除文件",git merge将尝试将该工作与其他人对该文件所做的任何工作结合起来。 (不过,Git唯一可以成功组合的"删除文件"工作也是"删除文件"。 因此,如果一个人执行了"删除文件"操作,而另一个人对该同名文件进行了"更改文件内容",Git 将在此处声明冲突,并让您(了解软件的人)弄清楚该怎么做。


1如果我们深入挖掘,这里真正的问题是分支这个词,它的定义很差。 参见 我们所说的"分支"到底是什么意思? 尽管如此,使用分支的大多数常见定义,对于某个文件是否"在"任何给定的分支中,我们没有得到一个合理的答案,因为它通常同时存在和不是。

2我在这里只是开玩笑:试图记住 Git 哈希 ID 可能对你的心理健康有害。 有一个空树,git rev-parse真的应该能够根据命令吐出来,但不是,所以你必须使用git hash-object来代替,以避免记住它。 很快,由于 SHA-256,将有两个。

3虽然拉取请求是特定于 GitHub 的项目(例如,GitLab 有"合并请求"),但它们与这里的核心 Git 共享很多。 GitHub上的绿色大按钮执行 Git 风格的合并。 不过,您可以将其切换到SQUASH ANDMERGE 或REBASE AND MERGE,它们是不同的,所以不要只是假设它总是相同的。

最新更新