为什么在Git中可以提交但不推送?

18

我正在开始学习Git。我一直在使用GitKraken,希望使用GUI来保存和共享文件是可行的途径。我更喜欢GUI而不是命令行。

现在我明白,在GUI中,我需要将文件stage,然后commit它们,最后push以上传它们。但是为什么pushcommit是两个不同的步骤呢?为什么我只想commit本地文件,而不跟着上传以保持文件同步呢?


5
由于您可能不会使用像CLI这样古老的东西,因此您可能无法想象这一点:离线工作。 - fredrik
4
当有 Git 的 GUI 应用程序时,为什么要学习 Git? - poke
3
不要轻易忽视命令行界面。许多优秀的开发者,包括年轻的开发者,在2018年选择使用它们有很好的理由。通常最好以开放的心态去接触陌生的事物,不幸的是你似乎正在做相反的事情。(另一方面,Git本身是在2005年创建的。尽管其界面有点老旧,但它是一个相当现代的工具)(还有一点需要注意的是,Vim和相关编辑器不需要你按i键才能响应。它的另一个模式——命令模式——是许多魔法发生的地方。只是你没有在输入缓冲区中键入内容而已。) - Chris
1
@kostix 我认为这个问题很好,除了CLI火焰(已经被移除)。一开始我也考虑过投票关闭,但是我的同事们新手使用git时经常问我这个问题。因为这里有3个好答案,所以将来直接指向这里可能会很好。 - Matt Messersmith
在命令行中学习Git,而不是在GUI中学习:https://www.youtube.com/watch?v=1mJQdcDi7z0&time_continue=2m - jub0bs
显示剩余4条评论
4个回答

41
一些(具体)原因。TLDR加粗。
第一,你可能无法推送到远程,因为你没有连接到互联网。
第二,有时候提交还没准备好推送。例如,我练习TDD。在我提交失败的测试后(我会这样做),我不想将其推送到远程,因为我的团队可能会拉取一个失败的测试套件。另一个常见的做法是在推送之前将这些提交压缩,使它们看起来像一个单一的功能。
第三个原因是这是一个你不想与任何人分享的个人项目,因此根本没有远程可推送。你不必在git repo中有一个远程。
第四个原因是你可能有多个远程(通常情况下,分布式语义会妨碍)。所以在提交后,git如何知道你要推送到哪个远程?全部?某一个?七个中的两个?由于git是分布式版本控制系统的语义,推送必须从git的角度明确指出。请参阅poke's答案获取更多详细信息。

P.S. 这个和问题不相关,但命令行Shell(包括bash)是非常强大的接口,一旦你学会了如何使用它们。在你熟练掌握这些工具后,使用它们比任何GUI都要快得多。这与你可以通过按键执行强大的操作而不是用鼠标有关,而且它可以无限定制以适应您的需求。


提交更改而不推送,允许在开发过程中本地完成保存-加载行为。一旦您对工作感到满意,然后进行提交和推送。这正确吗?“压缩提交”是什么意思?我谷歌了一下,我理解它的意思是合并提交?谢谢。 - marko-36
请注意,本答案主要关注于从此分离中获得的可能用例,例如在实际共享之前准备提交。但由于Git的分布式特性,也存在技术要求。 - poke
2
@Marko36 是的,你基本上已经明白了。一旦你对每个人都能看到的“新”状态感到满意,那么你就可以推送你的工作。这可能是在单个提交之后,也可能不是。压缩提交只是将一堆提交变成一个提交。所以如果我有10个提交,我可能不想让每个人都看到我做的10个提交。也许我在提交日志中说脏话,或者有些提交没有恢复的意义(比如失败的测试提交)。因此,你可以将提交压缩为1个提交(本地),然后推送该单个提交(与10个提交相同的内容)。 - Matt Messersmith
@poke 很好的观察,我已经更新了另一个具体的例子(用例),但试图暗示一下更抽象的分布式语义原因...希望这满足了你的好奇心。 - Matt Messersmith
1
@MattMessersmith 嗯,对我来说可以。顺便说一下,我的评论并不是批评,而只是为了指出你回答的重点。我认为我们的两个答案很配对,因为我完全关注技术方面,而你则涵盖了使用情况 :) - poke

8

Git是一种分布式版本控制系统,因此不存在像Subversion或甚至CVS那样的单一中央仓库。如果有一个单独的提交和推送命令,那么提交内容将会去哪里?远程仓库在哪里?

在Git中,没有中央仓库。甚至没有仓库的层次结构。对于本地仓库,任何其他仓库都是它可以交互的远程仓库。而本地仓库只是任何其他仓库的可能的远程仓库。

因此,本地和远程只是相对于您当前位置的视角:本地仓库始终是当前仓库,每个其他仓库都是您可以交互的远程仓库。

在使用Git时,您与之交互的是本地仓库:您本地提交所有更改。这具有许多好处和用例,我不会在此详细介绍,但本质上它是使版本控制分布式的原因,因为本地仓库具有所有信息、完整的历史记录。

因此,当您拥有具有完整历史记录和所有更改的本地仓库时,您需要一种与其他仓库进行交互的方式,以便允许您共享历史记录。这两种方法是推和拉(或获取)。由于分布式仓库每个仓库都是相同的,因此每个仓库都可以从另一个仓库推送或拉取(假设它们有访问权限)。

最终,提交和推送需要是分开的步骤,因为一方面是与(本地)仓库交互,而另一方面则是故意将更改共享到远程仓库。


7

另一个答案:没有很好的理由

在过去的日子里(就像五年前一样——按照今天的记忆标准,这已经是古代历史了),人们有时候 没有连接到互联网! 他们想要继续工作!所以他们在工作时就提交了代码。当连接实现后,他们会将所有提交推送上去。Git 就是以这种方式为主要范例而设计的。

现在跨越所有那些年代来到现在,软件版本控制机制(大致)没有改变。

有些人认为你应该将所有提交都保留在本地,直到你满意自己的代码非常健壮。我欣赏他们的本能:保护主要存储库代码;使它尽可能完美。是的,请务必这样做!

但 Git 提供了一种更适合不太完美代码的机制,它被称为分支。创建一个分支,在上面工作(同时推送提交),直到满意,然后将该分支合并到主干。这样,如果你的计算机遇到问题(硬盘崩溃、洒出咖啡、被盗等),你所有的工作仍然备份了。这就是版本控制的一点,对吧?

然而,还有其他人认为,在高度分布式的开发系统中,需要指定何时如何推送提交。这肯定是一个选择,但我还没有看到过这种做法。我想象不出一个公司会对其开发人员说:“你们每个人都去保留代码副本。我们将让你们随意推送和拉取,并希望什么都不会出错或变得混乱。” 是的,设置一个 Bitbucket 或 Github 帐户并告诉每个人:“使用这个作为你的源!”会更容易得多。

所以坦率地说:每次提交都推送。这样做没有任何不利影响,如果不这样做,可能会有一些小概率遗失工作。


3
它们有不同的用途。每个提交应该只更改代码的一个隔离方面;例如,重命名变量、将对一个函数的调用替换为对另一个函数的调用,甚至只是修复注释中的拼写错误。把它们看作是回滚点;如果我改变了我的想法,可以放弃一小部分提交并仍然保留这些其他无关的更改吗?
只有当您的一系列提交达到了已经经过足够测试并与您的同事或合作者共享的新稳定开发点时,才应该进行推送。
如果您正在修复较小的错误,每个提交都进行一次推送并不是不可能或不寻常的。但是大多数情况下,随着您朝着更大的目标前进,逐个提交更改是有道理的,并且只有在认为已经达到该目标时才进行推送。

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