在我正在阅读的 Git 教程中,git commit
用于存储您所做的更改。
那么 git push
有什么用呢?
基本上,git commit
“记录对存储库的更改”,而git push
“更新远程引用以及关联的对象”。所以第一个用于与您的本地存储库连接,而后一个用于与远程存储库交互。
这是来自 Oliver Steele 的一张漂亮图片,它解释了 Git 模型和命令:
https://i.stack.imgur.com/MgaV9.png
在 Pushing and pulling(我首先提到的那篇文章)上阅读有关 git push
和 git pull
的更多信息。
提交:将更改添加到本地存储库
push:将最后一次提交传输到远程服务器
好吧,基本上 Git commit 将您的更改放入本地存储库,而 git push 将您的更改发送到远程位置。
git push
是否上传实际更新的文件或一些特殊的“差异”文件?
git push
用于将您在本地存储库中完成的提交添加到远程存储库。与 git pull
一起,它允许人们进行协作。
提交:快照 |变更集 |版本 |历史记录 |存储库的“另存为”。 Git 存储库 = 提交的系列(树)。
本地存储库:您计算机上的存储库。
远程存储库:服务器上的存储库 (GitHub)。
git commit
:将新的 commit(上次 commit + staged 修改)附加到 local 存储库。 (提交存储在文件夹 /.git
中。)
git push
、git pull
:将 本地 存储库与其关联的 remote 存储库同步。 push
- 将 local 的更改应用到 remote,pull
- 将 remote 的更改应用到 local。
需要注意的三点:
工作目录——我们的代码文件所在的文件夹本地存储库——在我们的系统内部。当我们第一次执行提交命令时,这个本地存储库会在我们的工作目录所在的同一位置创建。 Checkit (.git) 文件被创建。之后,每当我们提交时,这会将我们在工作目录文件中所做的更改存储到本地存储库 (.git)。远程存储库——它位于我们系统之外,就像位于世界任何地方的服务器上一样,比如 GitHub。当我们发出推送命令时,来自本地存储库的代码将存储在此远程存储库中。
只想补充以下几点:
在您提交之前,您无法推送,因为我们使用 git push
将本地分支上的提交推送到远程存储库。
git push
命令采用两个参数:
远程名称,例如 origin
分支名称,例如 master
例如:
git push <REMOTENAME> <BRANCHNAME>
git push origin master
一个非常粗略的类比:如果我们将 git commit
与保存已编辑的文件进行比较,那么 git push
就是将该文件复制到另一个位置。
请不要把这个类比从这个上下文中拿出来——提交和推送并不像保存一个编辑过的文件并复制它。也就是说,为了比较,它应该成立。
如果您想象在 GitHub 上的存储库中维护一个日志文件,则更容易理解 Git 命令 add
和 commit
的使用。
对我来说,一个典型的项目日志文件可能如下所示:
---------------- Day 1 --------------------
Message: Completed Task A
Index of files changed: File1, File2
Message: Completed Task B
Index of files changed: File2, File3
-------------------------------------------
---------------- Day 2 --------------------
Message: Corrected typos
Index of files changed: File3, File1
-------------------------------------------
...
...
...and so on
我通常以 git pull
请求开始我的一天,并以 git push
请求结束。因此,一天的记录中的所有内容都对应于它们之间发生的事情。在每一天,我都会完成一项或多项需要更改一些文件的逻辑任务。在该任务期间编辑的文件列在索引中。
这些子任务中的每一个(此处的任务 A 和任务 B)都是单独的提交。 git add
命令将文件添加到“已更改文件索引”列表中。此过程也称为暂存,实际上记录更改的文件和执行的更改。 git commit
命令记录/完成更改和相应的索引列表以及可用于以后参考的自定义消息。
请记住,您仍然只是更改存储库的本地副本,而不是 GitHub 上的副本。在此之后,只有当您执行 git push
时,所有这些记录的更改以及每次提交的索引文件都会登录到主存储库(在 GitHub 上)。
例如,要获得该假想日志文件中的第二个条目,我会这样做:
git pull
# Make changes to File3 and File4
git add File3 File4
# Verify changes, run tests etc..
git commit -m 'Corrected typos'
git push
简而言之,git add
和 git commit
可让您将主存储库的更改分解为系统的逻辑子更改。正如其他答案和评论所指出的那样,它们当然还有更多用途。然而,这是最常见的用法之一,也是 Git 背后的驱动原理,它是一个多阶段的修订控制系统,与 SVN 等其他流行的系统不同。
Git 提交只不过是正式保存我们的更改。对于每个提交,我们都会给出提交消息,一旦我们完成提交,我们可以将其推送到远程以在全局范围内查看我们的更改。
这意味着我们可以在推送到远程之前进行多次提交(我们可以看到发生的提交列表和消息)。 Git 使用 40 位代码的提交 ID 保存每个提交。
而且我只在我想远程查看我的更改时才使用 Git 推送(之后我将检查我的代码是否在 Jenkins 中工作)。
提交更改时,将更改保存为本地存储库中的单个逻辑集。您可以多次执行此操作而无需推动。在它们被推送之前,它们不会离开您的本地存储库,这意味着远程存储库还没有这些更改集,因此当其他人从远程存储库中拉取时,您的提交将不会被拉取。
当您推送时,您在本地存储库中所做的所有提交都将传输到远程存储库,因此当共享此远程存储库的其他开发人员拉取时,他们会将您的更改传输到他们的本地存储库。检查 Git 命令和备忘单 here。
一个更简单的 Git 解释
我已经使用 Git 多年了,但奇怪的是这里或网上没有人似乎知道 Git 的 push
、pull
、commit
或 pull requests
是如何工作的。所以,下面是一个简单的解释。我希望它能更清楚地解释事情。它帮助了我!
您总是首先将代码保存在计算机上的“本地存储库”中,然后将更改上传到“远程存储库”。远程存储库分支中的更改会随着时间的推移被管理员“合并”到更大的远程存储库分支中,直到它们形成最终产品。这就是 Git 生产如何工作的简单解释。但真正发生的情况如下所述。
第一步始终是在本地计算机上编写和测试代码,使用 Git 作为源代码保存软件在后台运行。当您将本地代码保存在计算机上时,它不会像您想象的那样默认保存在 Git 中。您必须执行称为“提交”的第二步。 commit
与保存本地代码更改相同,但保存在“Git 世界”中。这让人们感到困惑。但是当我看到“commit”这个词时,我认为它是“Git Save”。这是一个额外的步骤,因为您已经保存了一次代码更改,现在必须将它们作为提交在 Git 系统中第二次保存,否则它们不会成为本地 Git 存储库系统的一部分。我认为“提交”是一些人认为 Git 设计不佳的原因之一。它只是不直观。
在您完成所有代码保存并将代码提交到本地 Git 存储库后,将完成 push
。 push 命令 将您的本地存储库更改(仅提交)发送到远程存储库,以便对其进行更新。当它这样做时,它将 100% 的更改完全写入远程存储库,因此两者是同步的,或者两者之间的代码 100% 匹配。将此视为“远程 Git 保存”。它使用您计算机上本地的内容覆盖远程存储库上的代码。起初这对我来说毫无意义。这不会删除遥控器上其他开发人员的更改吗?如果远程与您的更改发生冲突,或者您在本地存储库中首先需要的远程没有更改怎么办?起初这让我很困惑,因为没有人能在网上解释这是否与“合并”、“提交”、“拉取请求”等相同。事实证明,这只适用于一种条件。否则它会阻止你的推送并失败!
仅当您是唯一更改远程存储库的人并且两个代码库除了您在本地添加的提交之外相同时,“推送”才有效。否则,其他用户在该遥控器上所做的任何更改都将取消您的推送。因此,将 push
视为与您的本地代表相同的副本的“私人远程覆盖”。但是我们知道许多开发人员会像您一样使用推送将更改推送到远程副本,对吧?因此,在这种设计下,推送会失败,并且每个人的本地副本与远程副本都会不断地不同步。
正如我所提到的,如果远程存储库在您进行更改之前与您的本地存储库处于完全相同的状态,则此推送是仅允许的(不会在远程存储库中被阻止)。换句话说,您只能将本地更改推送到远程项目并使用 push
完全覆盖它,前提是您在推送本地更改时远程存储库没有被任何其他开发人员修改。这是 Git 令人困惑的一个奇怪方面。如果您的本地代码副本由于已更改而以任何方式与远程仓库不同步,则推送将失败,您将被迫执行 pull
或“rebase”,这是“更新”的一个花哨的词您的本地存储库首先使用远程副本”。如果您的推送被阻止,然后您执行 pull
,它将复制远程代码并将其代码更改“合并”到您的本地副本中。一旦再次同步,您仍然可以通过推送来推送您的提交,因为它们在拉取或合并之后仍然应该存在。
这在大多数情况下都非常有效,除非代码更改与提交冲突或您让其他开发人员也在同一代码区域中进行的代码更改。在这种极少数情况下,您必须先在本地解决冲突,然后才能继续进行其他任何操作,因为您可能会意外删除其他开发人员的更改。这就是 pull requests
(见下文)比推送更有帮助的地方,因为前者强制代码所有者或管理员首先在远程副本上手动解决主要代码更改,然后才允许任何代码更改远程存储库。
有趣的是,“拉”与“推”的作用相同,但在这种情况下,将最新远程项目的副本拉到您的本地 git 系统,然后将这些更改“合并”到您自己的副本中,而不是像“推”可以。当然,这会再次同步您的远程和本地副本,减去您设置为再次使用“推送”在远程存储库上更新的新提交。
通过 pull
将本地副本同步到远程后,您现在可以执行 push
并将您的 commits
或更改再次发送回远程副本并安全地覆盖它,因为您知道您已经合并了您的与所有其他开发人员所做的更改。
在 push
用您的本地副本覆盖远程副本后,远程与您的本地副本完全匹配。因为它们都匹配,所以您在本地进行的任何其他提交或保存都可以在没有拉取的情况下再次远程推送 - 只要没有开发人员像您一样更改远程。如果是这种情况,Git 将始终在推送时提醒您。你不能把它搞砸。但是一旦其他开发人员推送他们的更改,您就会再次不同步,并且在推送之前必须先再次拉取。
这种 commit-pull-push 是 Git 开发的真正节奏,没有人告诉你并假设你理解。大多数没有。它只是不直观或不合逻辑。
当然,无论如何,您都可以“强制”推送并覆盖所有内容。但是这个系统会在你尝试之前提醒你。当一名开发人员在他们拥有的一个远程存储库中更新一个分支时,这种拉取和推送系统总是能更好地工作。一旦有新人添加或更改遥控器中的任何内容,它就会失败。这就是导致推送和拉取警报和失败的原因,直到每个人都再次与遥控器同步。完成后,开发人员有权在他们的代码再次匹配远程时推送更改。
拉取请求
Git 谜题的最后一部分。这就是 pull requests
很重要的地方。在很多人不断拉动和推动对远程存储库的巨大更改以及大量冲突和合并的情况下,它们比推送更好。 pull request
一开始让我很困惑。如果您有 push
和 pull
Git 命令同步和合并代码,为什么需要拉取请求?
事实证明,pull request
是一种添加代码安全层的方法,在将大量代码编写或合并到关键的顶级远程分支或项目中的分支合并时,首先需要管理员或团队成员的许可。因此,它要求团队成员先批准大批量的本地 repo 代码更改并提交,然后再将它们拉入重要的远程 repo 分支。
这有助于首先通过代码审查和批准来保护对关键分支的代码更新。但它也允许许多团队更新远程仓库,以便在测试、批准等之前暂停更重要的分支和合并上的代码更改。这就是为什么开发人员私有的小代码分支只是简单地拉取和推送更改,但是这些分支的更大合并通常会被拉取请求阻止推送。这更典型的是使用推送完成的分支,然后将它们合并到 Git 树上的更大分支中。
弄清楚这一点需要花费数小时的研究,即使在我使用 Git 多年之后,因为没有在线文档解释这种差异。
所以....在处理您自己的代码更改或分配给您的项目部分时,请始终使用提交-拉-推例程。首先拉下存储库以确保您的本地存储库具有其他开发人员对其所做的所有最新更改。如果您愿意,可以在拉取之前和之后提交或保存所有本地更改……没关系。如果存在冲突,请尝试在本地解决它们。然后并且只有在那时,您才可以使用本地代码进行推送以覆盖远程副本。然后,您的本地和远程存储库在 Git 世界中 100% 同步!
请记住:只有在您的 Git 所有者和管理员也指示您时才执行 pull requests
,因为在这些情况下,您无权推送、更改代码或更新远程存储库,直到他们或团队手动批准您的代码更改并将它们合并到当前的 Git 远程项目。否则,commit-pull-push 就是您的 Git 工作流程!
git commit
是提交暂存在本地存储库中的文件。 git push
是将本地的master分支与远程的master分支快进合并。但合并不会总是成功。如果出现拒绝,您必须pull
才能成功git push
。
git push
使用的一种解决方案。实际上,git push
的目的地可以是任何 git 存储库。它可以位于另一个目录(例如git remote add clone ~/proj/clone.git; git push clone master
或git push ~/proj/clone.git master
)中您自己的本地硬盘驱动器上,也可以是您的 自己的 主机提供的 git 存储库。