我的 git 内部文件已更改。如何拉动他们的变化?

My git internal files changed. How to pull them with the changes?

所以我设置了一个 git 服务器,我正在使用它放置文件的文件夹,当你 推送到此服务器进行部署(这是 public、网站文件夹)。

我使用了这个指南: https://www.diffuse.nl/blog/how-to-set-up-git-for-automated-deployments

我 运行 遇到的问题是我更改了服务器文件夹中的那些内部文件,但是现在当我从服务器拉到我的本地计算机时,它 returns 旧版本回购,没有我从服务器所做的更改(我 vim-ed 进入文件并进行了更改,但没有告诉 git 这些更改..)

我想重新加载 git 服务器存储库,以便它识别并“看到”我对其“腹部”中的文件所做的更改。

提前致谢!

您链接的站点讨论了设置服务器端自动部署、推送部署模型,使用由单个 [=14= 组成的 Git post-接收挂钩] 带有 --git-dir--work-tree 选项和 -f 的命令强制从裸存储库检出到工作树中,对于 Git,它只是一个 临时 工作树。

这使用 Git 作为部署工具。 Git 是一个非常糟糕的部署工具,但在某些情况下,它已经足够了。如果您的情况是其中一种情况,那没关系。它不是很好,但它可以工作。但是,您确实需要了解它的局限性。

The problem I ran into is that I changed those internal files, in the server folder, but now when I pull from the server to my local machine, it returns the old version of the repo ...

Git 基本上对 文件 不感兴趣。 Git 实际上就是 提交 。一个裸存储库,这是您在服务器上设置的那种,根本没有任何工作树。 (这就是 post-receive 挂钩临时设置一个的原因,它的长度足以将 Git 用作糟糕的部署工具。)

这意味着您必须准确理解提交是什么,以及提交对您有何作用。提交是一种打包交易,包含两件事。每个提交也是 编号 ,用 hexadecimal 表示的唯一的、丑陋的大数字。 Git 迫切需要这些数字:这是 Git 可以 找到 提交的唯一方法,通过它的数字。但是我们——人类——不擅长数字,所以 Git 给了我们一个辅助系统,通过它 我们 可以 Git store 名称 中的数字,例如分支名称。然后我们让 Git 存储正确的数字,我们给 Git 名称: master,或 main,或任何名称我们喜欢。

提交的两个部分是:

  • 一次提交包含每个文件的一个快照,作为一个永久冻结的存档。因此,即使 Git 仅存储 commits,您也可以从提交中获取文件 out,因为提交包含文件。提交中的文件(在这个冻结的存档中)采用特殊格式,其中文件被压缩并 去重。这考虑了这样一个事实,即大多数提交大多与大多数其他提交具有相同的文件。如果你有一个大文件——几十或几百兆字节现在仍然很大,尽管它正在变小——在一千次或更多次提交中,实际上只有 一个副本 该文件,感谢去重。

  • 而且,每个提交都会存储一些元数据,或者关于提交本身的信息。例如,每个提交都会存储其作者的姓名和电子邮件地址。它还存储提交者信息。有两个日期和时间戳,还有一个自由格式区域,当您进行提交时,您可以在其中提供 提交消息 以供将来参考。

整个提交,而不仅仅是快照,被永久冻结。这就是提交编号的生成方式。不可能更改有关提交的任何内容,因为如果您 do 从所有提交的大数据库中取出一个提交,由 Git 中的编号索引 key-value store,然后更改其中的内容并将其放回去,您得到的是 new 提交,具有一个新的且不同的唯一编号。旧的提交仍然在那里,在它的旧编号下。所以 Git 存储库永远不会缩小:它只会添加 new 提交。1

但是,除了这个元数据之外,每个提交 存储一些早期提交或提交的 提交编号 — 或哈希 ID。 2 大多数提交,我们称之为“普通”提交,只有一个先前的提交编号。这是提交的 parent,这意味着分支中的提交形成一个简单的向后查找字符串:

... <-F <-G <-H

这里的 H 代表提交链中 last 提交的哈希 ID。提交 H 在其元数据中包含较早提交 G 的实际(丑陋的)哈希 ID,它又存储更早提交 F 的哈希 ID,依此类推.这样,Git 只需要知道某个提交链中 last 提交的哈希 ID。它可以自己找到所有 earlier 提交。而且,正如我之前提到的,我们人类通常使用 分支名称 来存储此哈希 ID:

...--F--G--H   <-- master

这里的namemaster为我们存储了hash ID,这样我们就不用死记硬背了。如果我们添加一个 new 提交,Git 会自动为我们更新我们的名字 master:

...--F--G--H--I   <-- master

名称 master 现在指向提交 I,而不是提交 H,我们再次使用名称 master 来表示 给我获取链中的最新提交.

合并提交 是有两个或两个或更多父级的提交;这些将两个独立的提交链放在一起,这样一个分支名称可以找到多个以前的提交:

          I--J
         /    \
...--G--H      M--N   <-- master
         \    /
          K--L

这条链在 H 之后“分开”——变成了两个分支——但是当我们将其中一个分支合并回 master 时,它在 M 处“重新加入”。然后我们删除了另一个 分支名称 ,因为我们不再需要它了,现在我们在合并 blob 的两边都有一个简单的链。

所有这些都是由两件事构建的:名称,它找到我们可以向后工作的提交,以及提交,它存储存档的快照和元数据。这就是Git 是关于什么的。这不是关于 files,而是关于 commits,我们发现它使用其他提交——当我们向后工作时——and/or 名称,当我们想直接进行一些特定的提交。仅此而已!

当我们将两个 Git 相互连接时,我们选择一个 Git 作为发送方,一个作为接收方。发送者和接收者相互交谈,以确定他们已经有哪些提交。他们通过提交 numbers 来做到这一点,因为它们是通用的。多亏了加密散列函数的魔力,如果一个 Git 和另一个 Git 具有相同的提交编号,则可以确保它们具有 完全相同的提交 。如果一个 Git 有另一个 Git 缺少的提交编号,则缺少的 Git 需要从拥有的 Git 中获取该提交。只要 having Git 是发送者,我们已经告诉它发送提交,3


1可以从存储库中删除旧的、死的提交。故意 这样做是相当棘手的,但是某些操作会自然地生成死提交,并且 Git 最终会自行清除它们。然而,分布式版本控制的本质意味着,如果您对某些 other 存储库进行了一些提交,即使您认为已将其杀死,它也可以恢复。

(我没能在这里找到适合“僵尸提交”的图片...)

2当然也有例外。至少有一个提交,在任何有提交的存储库中,不能有一个父提交,因为它是第一个提交。所以那个提交根本没有父提交号。您可以创建额外的无父提交(事实上 git stash 有时出于自己的目的这样做);这样的提交是 root 提交.

3一般来说,提交不能被限制,尽管一些Git附加组件尝试。但是,当我们使用 git push 时,我们选择 final 提交,我们将要求我们的 Git 发送——如果需要,他们的祖先提交将随行——当我们使用 git fetch 时,这与 git push 相反,如果我们愿意,我们可以让我们的接收 Git 不必费心向发送者询问一些提交。不过,通常的默认设置是获取所有内容。


文件的来源

关于提交及其存档的事情是,就其本身而言,它们非常无用。 只有Git可以读取这些东西,根本没有任何东西可以写入它们。它们将永远冻结:我们可以制作新的,但不能覆盖旧的。

但是,要完成任何 工作,我们需要 文件。这就是我们今天的计算机使用文件的方式。所以我们必须有两件事:

  • 我们需要一种方法来告诉 Git:提取此提交。那是 git checkout(或者,因为 Git 2.23,git switch,尽管 git checkout 仍然有效)。

  • 而且,我们需要一种方法来进行新提交

这两个操作都需要Git所谓的工作树。该工作树是文件所在的位置。您使用 git checkoutgit switch 创建初始集。然后你工作 on/with 他们,使用 git add 更新 Git 的副本——这涉及 Git 的 index,我我不打算进入这里 — git commit 进行新的提交:一个新的快照加上元数据。这会为您的历史记录添加一个新的提交;您现有的历史记录,包括所有现有的 Git 提交,保持不受干扰。

您服务器上的工作树是临时工作树。您的服务器 Git 在您一键部署后就忘记了它的存在。因此,您在此工作树中所做的任何事情都无法将其返回服务器上的Git存储库。 4事实是,您不打算使用此设置在服务器本身上做任何工作

相反,您应该做的是在您的笔记本电脑(或您在与服务器连接结束时使用的任何计算机)上工作。您可以在那里进行任何更新,然后使用 git commit 进行新的提交。然后您使用 git push 将新的提交从您的笔记本电脑发送到服务器。服务器的 Git 接受这些新提交,5 然后那个糟糕的(但可用)post-receive 钩子用于 deploy 最新 master 提交。7

简而言之,您在错误的机器上更新文件。


4这不是 完全 正确,因为您可以 运行 git --git-dir=... 临时挂钩该工作树备份到 Git 存储库。但这超出了 Git 的设计范围,也超出了这个答案的范围。

5或者,它会根据您设置的接受和拒绝标准拒绝它们。这一切都是完全可控的,但如果您选择控制它,则需要在服务器端进行 lot 编程。这就是 GitHub 和 Bitbucket 等托管网站简化控制的原因。他们将全部权力——以及随之而来的重大责任6——留给自己,并把它的一些小的、更容易使用的片段分发给你。

6是的,这是蜘蛛侠的参考。然而,这个概念可以追溯到 quite a bit further.

7实际部署的提交取决于您在脚本中为 git checkout 命令指定的分支名称。您是否在脚本中提供了分支名称?如果不是,请阅读 the git checkout documentation 以找出 Git 将在此处使用的分支名称。