我在另一个分支上从远程分支拉取时有点困惑。例如,如果我更改为 main,则拉取:
git checkout main
git pull
我得到了远程更改的更新。好的。
但是,如果我在另一个分支上并且我想更新 main 而不更改为 main,我总是会得到令我困惑的结果(除非我更改为 main,否则我不会真正获得更新)。
假设我在分支“feature”上,我尝试:
git pull main或git pull origin/main或git pull origin main,我得到了一些我没有预料到的东西,但从来没有更新过的分支。
一个具体的例子,git pull origin main在分支上运行时feature,将输出以下内容:
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), done.
From <repo name>
* branch master -> FETCH_HEAD
8a84194..d00d469 master -> origin/main
Updating 340286a..d00d469
Fast-forward
Run Code Online (Sandbox Code Playgroud)
但是当我更改为 main 时git checkout main,然后git pull,我得到了实际的更新:
git pull
Updating 8a84194..d00d469
Fast-forward
Pipfile | 2 +-
Pipfile.lock | 1583 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------
setup.py | 2 +-
3 files changed, 863 insertions(+), 724 deletions(-)
Run Code Online (Sandbox Code Playgroud)
你能帮我理解我做错了什么吗?谢谢你!
罗伊.
首先,除了您现在签出的分支之外,您实际上无法合并到任何其他分支中。1
\n其次,2的git pull含义是:
git fetch,然后第二个 Git 命令是您的选择,但如果没有做出明确的选择,您通常会得到git merge. 所以pull= fetch+ merge,并且merge仅适用于当前分支。
(你的另一个正常选择是git rebase。但是有同样的限制,即只能在你现在git rebase签出的任何分支上工作。它也有一些脚注,因为 Git 不能忍受让任何事情变得简单,但我们再次忽略这些.)
因此,初步近似:
\ngit pull意味着选择该分支的上游,然后拉入该分支(我们稍后将定义上游);git pull origin main意味着复杂的事情,我稍后会描述;和git checkout main然后git pull意味着选择 的上游main,并拉入,main因为“这个分支”是main。除非您已经打开main,否则这三个命令都不能与其他任何命令交换。
1对于这个 \xe2\x80\x94 特殊情况有许多注意事项,例如,这些特殊情况看起来像是合并,而即将推出的未来 Git 软件可能最终会逃脱这个约束 \xe2\x80\x94 但现在只是将其视为真理。
\n2在过去(如 2015 年之前,Git 2.6 之前),它git pull实际上是一个运行 的 shell 脚本git fetch,然后运行相应的第二个命令。C 版本更快、更高效,但内部逻辑仍然相同。
您可能使用 Git 来维护一堆文件。但 Git 并不是真正与文件有关的。您也可以使用分支,但 Git 也与分支无关。最后,Git 就是提交。确实,提交包含文件,我们使用分支名称来帮助我们(和 Git)查找提交,但 Git 与文件或分支名称无关:它存在的理由\'\xc3\xaatre是提交。
\n因此,您需要了解 Git 提交是什么以及它为您做什么。幸运的是,这部分非常简单。Git 提交:
\n已编号。每次提交都会获得一个唯一的哈希 ID。哈希 ID 巨大、丑陋且随机,人类不可能记住。它必须是,因为它必须是唯一的:当您进行新的提交时,它必须获得一个以前从未使用过的数字,并且现在该数字永远不能再用于任何其他提交。
\n(由于鸽巢原理,这部分在数学上是不可能的,但是由于哈希 ID 很大,因此将不可避免的失败推迟到未来,到那时我们都计划死掉,所以我们不在乎。)
\n因为每个提交都有git fetch一个唯一的编号,所以我们可以使用任意两个 Git 存储库并使用或简单地相互介绍它们git push。一个 Git 是发送者,一个是接收者。发送者列出他的提交哈希 ID,接收者检查他是否有这些哈希 ID。如果他这样做了,他就有了这些承诺。如果没有,他可以知道他已经拥有哪些提交以及他需要哪些提交,然后接收者让发送者发送接收者需要的任何提交。现在两个 Git 存储库共享提交。(你必须将它们连接两次,每个方向一次,才能获得完全共享,并且有很多方法可以限制共享,但这是一般原则。)
完全只读:任何提交一旦完成就不能更改。这是使哈希 ID 技巧发挥作用所必需的。
\n包含两件事:所有源文件的完整快照,以您(或任何人)提交时的形式永久冻结,以及一些元数据。元数据包括您的姓名、电子邮件地址以及提交时的日期和时间戳等内容。但是元数据中还有很多其他内容,特别是 Git 添加了自己的早期提交哈希 ID 列表。
\n这个早期提交哈希 ID 列表位于每个提交的元数据内,向后连接提交。大多数提交(到目前为止)都有一个这样的哈希 ID,这些是我们首先要关注的。当我们确实有一个哈希 ID 时,Git 将这一哈希 ID 称为提交的父级。我们说提交指向其父级。这为我们提供了一种绘制提交的方法。
\n假设您的存储库中的最新提交有一些丑陋的大哈希 ID,我们将其称为H“哈希”。CommitH存储一些早期提交的哈希 ID:一个不同的、看起来又大又丑、随机的东西,我们称之为G。这意味着提交H 指向较早的提交G:
G <-H\nRun Code Online (Sandbox Code Playgroud)\n但它是一次提交,因此它的G元数据中也有一个哈希 ID 。它指向一些较早的提交;我们称其为:F
... <-F <-G <-H\nRun Code Online (Sandbox Code Playgroud)\n提交F具有元数据,因此它指向另一个较早的提交,并且这将永远持续\xe2\x80\x94,或者至少,直到我们回到有史以来的第一个提交,它实际上无法指向任何内容早些时候。所以它没有:它有一个空的先前提交列表。如果我们调用该提交A(并声称我们正好有 8 个提交),则整个链是:
A--B--C--D--E--F--G--H\nRun Code Online (Sandbox Code Playgroud)\n我懒得把箭头画成箭头。它们都是提交的一部分,永远不会改变:H 总是向后指向G、永远,以及G向后指向F永远,等等。
为了让这一切发挥作用,Git 需要一种快速的方法来查找commit H。通常,Git 使用由哈希 ID索引的简单键值存储,通过哈希 ID 记录其所有内部对象\xe2\x80\x94 提交及其支持内容\xe2\x80\x94。那么Git快速查找的方法H就是知道它的哈希ID。
现在,您可以记住每个 Git 提交哈希 ID。但这样才是疯狂所在。与其让我们记住哈希 ID,为什么不让计算机来记忆呢?来记忆呢?这是分支和其他名称的用武之地:
\n...--G--H <-- main\nRun Code Online (Sandbox Code Playgroud)\n分支名称 main\xe2\x80\x94 是一个可更改的指针,与卡在提交元数据\xe2\x80\x94 中的指针不同,它告诉我们哪个提交是 main. 如果我们进行更新的提交I,Git 会安排I向后指向H:
...--G--H <-- main\n \\\n I\nRun Code Online (Sandbox Code Playgroud)\n然后会重新指向名称 main指向较新的提交:
...--G--H\n \\\n I <-- main\nRun Code Online (Sandbox Code Playgroud)\n现在最新的提交main是 commit I,而不是 commitH。
让我们回到这一设置,只有一个分支名称main:
...--G--H <-- main\nRun Code Online (Sandbox Code Playgroud)\n现在让我们创建一个新的分支名称,例如develop. 在 Git 中,分支名称必须恰好指向一次提交。我们可以选择八个提交中的任何一个,但这里最合适的一个可能是最新的一个,如果我们用来git branch develop创建它,那么 Git 会在这里选择一个。现在我们有:
...--G--H <-- develop, main\nRun Code Online (Sandbox Code Playgroud)\n目前,两个名称都选择 commitH,但是一旦我们开始进行新的提交,这种情况就会改变。因此我们需要知道使用哪个名称H来查找 commit 。为了在我们的绘图中标记这一点,让我们将名称HEAD(全部大写)附加到一个分支名称上:
...--G--H <-- develop, main (HEAD)\nRun Code Online (Sandbox Code Playgroud)\nH我们现在正在使用 commit ,但是通过name main来实现。如果我们运行:
git checkout develop # or git switch develop, which does the same\nRun Code Online (Sandbox Code Playgroud)\n我们得到:
\n...--G--H <-- develop (HEAD), main\nRun Code Online (Sandbox Code Playgroud)\n我们仍在使用commit ,但我们现在通过名称H来这样做。 develop
如果我们I现在进行新的提交,它的制作方式与我们在 上时的方式相同main,但由于我们现在正在使用,所以更新的develop是这个名称:
...--G--H <-- main\n \\\n I <-- develop (HEAD)\nRun Code Online (Sandbox Code Playgroud)\n该名称main没有移动,因为它不是我们正在使用的名称。
这是 Git 中的一般规则:每当您进行新的提交时,Git 都会更新当前的分支名称。这就是HEAD所附的名称。因此,如果您绘制提交(在纸上或白板上,或者使用git log --graphGit 绘制它们),您将看到您现在所在的位置以及新提交将去往的位置。它会在您使用的任何提交之后通过您使用的任何名称添加 on 。
git merge现在看看假设我们从以下内容开始:
\n...--G--H <-- main\nRun Code Online (Sandbox Code Playgroud)\n并创建两个新的分支名称,br1并且br2也指向H。我们也将很快停止以名字绘制 main只是为了稍微整理一下绘图。所以现在我们有:
...--G--H <-- br1, br2, main (HEAD)\nRun Code Online (Sandbox Code Playgroud)\n我们现在选择br1当前分支并进行新的提交:
I <-- br1 (HEAD)\n /\n...--G--H <-- br2, main\nRun Code Online (Sandbox Code Playgroud)\n当我们进行第二次提交时,我们得到:
\n I--J <-- br1 (HEAD)\n /\n...--G--H <-- br2, main\nRun Code Online (Sandbox Code Playgroud)\n然后我们切换到分支名称br2,以便我们返回到提交时保存的文件H,并开始进行一些不同的更改br2:
I--J <-- br1\n /\n...--G--H <-- main\n \\\n K--L <-- br2 (HEAD)\nRun Code Online (Sandbox Code Playgroud)\n如果我们git switch br1再次让 Git 用 commit-L文件替换 commit-J文件并“on”br1文件并再次
I--J <-- br1 (HEAD)\n /\n...--G--H\n \\\n K--L <-- br2\nRun Code Online (Sandbox Code Playgroud)\n如果我们现在运行:
\ngit merge br2\nRun Code Online (Sandbox Code Playgroud)\nGit 会完成复杂的合并过程。跳过如何部分,让我们看看合并的结果:如果一切顺利,Git 会进行新的合并提交 M。合并提交的原因M在于,它不像任何新提交那样仅仅指向 commit J,而是还指向 commit L,如下所示:
I--J\n / \\\n...--G--H M <-- br1 (HEAD)\n \\ /\n K--L <-- br2\nRun Code Online (Sandbox Code Playgroud)\n(现在你知道为什么我停止画名字了main:它仍然在那里,只是很难画它并提交M)。
这是真正的合并。为了实现这一目标,Git 必须结合工作: Git 必须弄清楚H和之间发生了什么变化J,以及H和之间发生了什么变化L。我们首先跳过了这一点以及Git 如何选择提交H,但事实是 Git确实在这里选择H。提交H是最好的共享提交,在分支和. 所有提交(包括在内)都在两个分支上。Git 调用合并基础来执行此合并操作。br1 br2HH
然后 Git 必须为提交创建一个新的快照,将组合M工作应用于来自 的快照,从而保留您的更改并添加他们的更改,或者 \xe2\x80\x94(如果您想以相反的方式查看它)\xe2\x80 \x94保留他们的更改并添加您的更改(请注意,对于正常的日常合并,无论哪种方式,结果都是相同的)。H
这种工作组合需要检查两个分支之一。合并提交M被添加到该分支,这就是为什么br1现在指向M. 其他分支名称不会移动:只有当前名称会受到添加新提交的影响。
并非所有合并都是真正的合并。 假设我们不是创建两个分支br1和,并在两个分支上br2进行新的提交,而是从和开始,仅在 上进行两次提交,然后切换回mainbr1br1main:
I--J <-- br1\n /\n...--G--H <-- main (HEAD)\nRun Code Online (Sandbox Code Playgroud)\n如果我们现在运行git merge br1,Git 将执行以下操作:
H再次提交。H和提交H(合并的“我们”一侧)之间完成了哪些工作,以及提交H和提交J(合并的“他们”一侧)之间完成了哪些工作。但提交H 就是提交H。“我们”这边根本没有工作!由于合并基础提交是当前提交(通过遵循HEAD提交的分支名称来选择),因此没有需要合并的不同工作。进行真正合并的结果将是一个合并提交,其快照与commit中J的现有快照完全匹配。
因此Gitgit merge走了一条捷径。您可以使用 告诉它不要这样做git merge --no-ff,但默认情况下,Git 会执行快进而 不是合并。(Git 将其称为快进合并,但不涉及实际的合并。)为此,Git 只需将当前分支名称向前滑动以指向另一个提交,然后检查该提交,就像通过git checkout:
I--J <-- br1, main (HEAD)\n /\n...--G--H\nRun Code Online (Sandbox Code Playgroud)\n(没有理由再担心图表中的扭结,但我暂时将其保留)。
\n请注意,与常规合并一样,此快进合并移动了分支名称。但它没有进行任何新的提交,这就是它的特别之处。 事实上,它没有进行任何新的提交,这意味着将来我们可能永远不知道 Git 做了这件事。 如果我们现在删除该名称 br1,我们会得到:
...--G--H--I--J <-- main (HEAD)\nRun Code Online (Sandbox Code Playgroud)\n看起来我们一直都在 main做出承诺。
git fetch我已经git fetch在基本背景部分提到过。这就是你如何连接你的Git 软件,在你的 Git 存储库上工作/与其他一些Git 软件\xe2\x80\x94任何使用 Git 协议的东西,实际上\xe2\x80\x94\正在与其他一些工作一起工作存储库。如果我们将 your-software-plus-your-repository 称为“your Git”,将 other-software-plus-other-repository 称为“他们的 Git”,则:
这里的技巧是 Git 创建和/或更新的名称根本不是分支名称。原因是你的分支名称是你的。 你做了br1并且br2(或没有)。您main正在跟踪您的提交添加的提交。覆盖这些名称来跟踪其他一些 Git 的提交是很糟糕的!
所以你的 Git 根本不这样做。相反,您的 Git 采用每个 Git 分支名称,例如main和develop、feature/tallSticks origin(或其他名称,但让我们使用origin)以及每个分支前面的斜杠。他们main成为你的origin/main,他们develop成为你的origin/develop,等等。
您的 Git 现在创建或更新这些名称,这是您的 Git 记住其 Git分支名称的方式。所以现在你可能有:
\n I--J <-- main (HEAD)\n /\n...--G--H\n \\\n K--L <-- origin/main\nRun Code Online (Sandbox Code Playgroud)\n在您的存储库中,或者可能:
\n I--J <-- br1 (HEAD)\n /\n...--G--H <-- main\n \\\n K--L <-- origin/main\nRun Code Online (Sandbox Code Playgroud)\n取决于您对分支名称所做的操作。 他们的 main\xe2\x80\x94your origin/main\xe2\x80\x94 已从指向H,您之前的指向 ,移动到指向L,因为他们添加了两个您没有的提交。你的 Git 从他们的 Git 中获取了这两个提交,并将它们放入你的存储库中,现在它们与 Git 的两个提交具有相同的哈希 ID,因为它们是相同的提交:在保存方面是逐位相同的快照和元数据,包括父哈希 ID。
如果你跑去git checkout main得到这个:
I--J <-- br1\n /\n...--G--H <-- main (HEAD)\n \\\n K--L <-- origin/main\nRun Code Online (Sandbox Code Playgroud)\n你现在可以运行了git merge origin/main。您的 Git 将找到此操作的合并基础commit H,并注意这不需要真正的合并,而是可以执行快进,您将得到:
I--J <-- br1\n /\n...--G--H--K--L <-- main (HEAD), origin/main\nRun Code Online (Sandbox Code Playgroud)\n在你自己的存储库中(这次我解决了这个问题)。
\n请注意,这些origin/带有 - 前缀的名称不是分支名称。我称它们为远程跟踪名称。Git 的文档将它们称为远程跟踪分支名称,但它们根本不是分支名称:它们是其他人的分支名称的反映,但它们实际上并不是存储库中的分支名称。
现在我们来谈谈分支的上游设置。存储库中的每个分支名称(但不是任何远程跟踪名称)都可以有一个上游集。这是可选的,因此每个分支名称不能有上游。设置上游不会以任何方式更改分支。它只是使某些操作更加方便:
\ngit merge在没有命名任何内容的情况下运行,Git 将使用当前分支的上游设置。也就是说,git merge origin/main表示查找由 命名的提交origin/main,git merge表示查找由当前分支的上游命名的提交。git rebase在没有命名任何内容的情况下运行,Git 将使用当前分支的上游。git pull,Git 将使用当前分支的上游。git status,Git 会在状态中添加一些使用当前分支的上游获取的信息。这些并不是唯一的事情,但可以说它们是亮点。设置上游使 Git 更容易使用。但是,唉,每个分支名称只能获得一个,而且您几乎应该始终将上游的那个名称设置为相应的远程跟踪名称。即,main应该是 的上游,应该是origin/main的上游,依此类推。developorigin/develop
(这里有一个小故障:feature/roy例如,当您编写自己的新分支名称 \xe2\x80\x94 或br1,或其他 \xe2\x80\x94时,还没有相应的分支。origin所以有\'否origin/roy或origin/br1,你还不能设置上游。Git 让你等待,直到你使用了git push。我们稍后会再讨论这一点。)
我们现在知道:
\ngit fetch从其他一些 Git(例如 at origin)获取新提交并更新相应的远程跟踪名称;和git merge,自行运行,与上游合并,根据需要进行快进或真正的合并。首先运行git pull检查是否存在上游集(以便它可以执行该git merge步骤),然后为您执行这两个命令。这就是它真正所做的一切。
但是等等,等等,那又怎样呢git pull origin main?好吧,如果您还没有上游集\xe2\x80\x94,或者即使您有\xe2\x80\x94,也git pull origin main会让您的命令运行。首先,git pull将行的其余部分传递给 git fetch,以便您运行:
git fetch origin main\nRun Code Online (Sandbox Code Playgroud)\n该git fetch命令通常使用上游(origin/main例如)来知道要转到origin,但这里我们明确告诉它“使用 Git over at origin”。这里的最后一个main告诉它我们对哪个分支名称特别感兴趣:它限制了 fetch。通常,您的 Git 会让 Git 列出所有分支名称,并带来所有新提交。使用此命令,您的 Git 仅向其 Git 询问其main.
(这通常根本没有节省,因为稍后您将需要来自其他分支的其他提交,如果您一次获得所有内容,那实际上比运行多个操作更有效git fetch。但它会加快速度有时,这 git fetch有点;只是它会在以后发生 git fetch速度比原来慢。可以说,现在保存,以后付款。除非您的网络连接速度非常慢或获取的数据异常巨大,否则它\很少值得做。)
不管怎样,无论是否带来了任何新的提交main,你的 Git 都会更新你的origin/main. 然后你的git pull运行:
git merge -m "merge branch \'main\' of <url> [into ...]" origin/main\nRun Code Online (Sandbox Code Playgroud)\n(或多或少\xe2\x80\x94这里实际上使用了原始哈希ID,而不是名称origin/main,但效果是相同的)。因此,您会得到引用其他 Git 的 URL 及其分支名称的合并main。
由于不需要上游设置,这将获取他们的提交,更新您的origin/main,然后与您的origin/main. 您可以通过运行以下命令获得等效的结果:
git fetch\ngit merge origin/main\nRun Code Online (Sandbox Code Playgroud)\n尽管现在的消息是:
\nmerge branch \'origin/main\' [into ...]\nRun Code Online (Sandbox Code Playgroud)\n即只git fetch知道实际使用的URL;到运行时,git merge它并不知道origin/main刚刚从该 URL 更新了。代码git pull知道,因为git pull代码为您运行 ,所以代码提供了替代日志消息。(实际上,这两条日志消息都没有任何好处。 他们还不如直接说或。)git fetchgit pullhere have codehaaaaaands
git push在您的存储库中进行新的提交后,无论是使用git commit、 、git merge、git merge-as-run-by-git pull或其他方式,在某个时刻您应该将这些新提交发送到其他一些 Git。这里通常的候选者是位于 的 Git origin。要推送一些提交,您将运行,例如:
git push origin br1\nRun Code Online (Sandbox Code Playgroud)\n这里的部分origin表示联系该名称下存储的URL处应答的Gitorigin,即含义与 for 基本相同git fetch。这里的部分br1是如何提供两件事:
请注意,与在存储库中git fetch创建或更新远程跟踪git push名称不同,命令提供分支名称供它们在存储库中设置。这是因为这里没有任何远程跟踪名称的概念。您通常会选择一个您希望他们设置的分支名称;当你使用时,git fetch你通常想要获取他们所有的分支名称,并且你不知道他们创建了哪些名称,所以我们需要一些奇特的东西,比如远程跟踪名称。
无论如何,所有这一切的结果是你的 Git 将你的提交交给了他们的 Git(在你的 上br1,他们还没有;你br1可能还有数十或数千个提交,他们在他们的或其他地方有main)您的 Git 不需要发送这些内容,因为两个 Git 已经交换了哈希 ID 并意识到这些 ID 已经共享)。然后,您的 Git 礼貌地要求他们的 Git 创建或更新它们 br1以合并新的提交。
如果他们还没有,br1他们可能会遵守。(一些托管站点,如 Bitbucket、GitHub 和 GitLab 添加了权限规则,但基础 Git 没有任何这样的东西。)或者也许他们确实有一个:br1在这种情况下,只有在添加这些提交导致对他们来说是快进操作。也就是说,假设您有:
I--J <-- br1\n /\n...--G--H <-- main\nRun Code Online (Sandbox Code Playgroud)\n然后你就跑git push origin br1。他们有:
...--G--H <-- br1, main\nRun Code Online (Sandbox Code Playgroud)\n如果他们将I-J其放入存储库中,他们现在可以向前滑动名称br1,以便他们拥有您拥有的所有提交,并且他们br1现在也指向J。但如果他们有:
...--G--H <-- main\n \\\n K <-- br1\nRun Code Online (Sandbox Code Playgroud)\n在他们的存储库中,然后你给他们I-J,他们这边的结果如下所示:
I--J [polite request: move `br1` here]\n /\n...--G--H <-- main\n \\\n K <-- br1\nRun Code Online (Sandbox Code Playgroud)\n如果他们这样做,他们就会失去 K他们的br1。这是因为 Git通过读取分支名称然后向后工作(通过那些将提交与早期提交连接起来的向后指向的箭头)来查找提交。Git 无法前进,因为箭头不指向前方(并且是提交的一部分并且无法更改:它们永远指向后方)。因此,对于这种情况,他们会说:不,我不能添加到 my 中,因为这会丢失一些提交,Git 将其报告为非快进错误。I-Jbr1
注意,git push 不运行git merge。它只是尝试按原样添加提交。如果您需要I-J与他们合并K,则必须运行git fetch才能提交K并origin/br1更新。然后您可以合并以便I-J 添加(在您的存储库中):
I--J-----------M <-- br1 (HEAD)\n / /\n...--G--H <-- main /\n \\ ___________/\n K <-- origin/br1\nRun Code Online (Sandbox Code Playgroud)\n因为新的合并提交M指向和 K ,所以现在这会添加到 他们的(您的)J上,并且他们将接受发送给他们的请求并要求他们将其设置为指向。 br1origin/br1I-J-Mbr1M
(您还可以选择变基而不是合并,但我们不会在这里讨论这个。)
\n现在,对于他们之前没有的情况,br1您将拥有:
I--J <-- br1\n /\n...--G--H <-- main, origin/main\nRun Code Online (Sandbox Code Playgroud)\n在你的存储库中。你不会有一个origin/br1. 所以你运行:
git push origin br1\nRun Code Online (Sandbox Code Playgroud)\n并派他们I-J去要求他们创造 br1,他们服从了。您的 Git 看到他们接受了礼貌的请求,现在您的 Git 在您的存储库中创建了您的origin/br1:
I--J <-- br1, origin/br1\n /\n...--G--H <-- main, origin/main\nRun Code Online (Sandbox Code Playgroud)\n您现在可以将(your) 的上游br1设置为 (your) origin/br1:
git branch --set-upstream-to=origin/br1 br1\nRun Code Online (Sandbox Code Playgroud)\n例如。但是,您不需要将其作为单独的命令输入,而是git push允许您添加-u标志:
git push -u origin br1\nRun Code Online (Sandbox Code Playgroud)\n该-u标志告诉git push:如果推送成功,则将刚刚推送的名称的上游设置为相应的远程跟踪名称。也就是说,在这种情况下,意味着将上游设置br1为origin/br1。请注意,如果推送失败,该-u标志不起作用。
-u即使现在有上游集,您也可以使用该标志。它只会运行该git branch --set-upstream-to命令并用新设置覆盖当前设置。(如果 的上游br1已经origin/br1,这会覆盖旧origin/br1的origin/br1,所以你甚至无法知道发生了什么。)但是大多数人更喜欢origin在他们的头脑中将“创建新分支”与“更新现有分支”分开关于起源”。如果您也喜欢这个,您就会知道何时要添加-u(在那里创建分支并在此处设置上游)以及何时不添加(在那里更新分支,不必在这里做任何事情)。
一旦您将上游设置为br1to origin/br1,通常的 Git 设置意味着您可以在打开git push时运行。因此,当您创建它时,您只需要一次,之后您只需运行即可,无需额外输入。 br1git push -u origin br1 git push
您概述的三个命令都非常不同。它们都是基于这样的事实构建的:git pull默认情况下,运行
| 归档时间: |
|
| 查看次数: |
1441 次 |
| 最近记录: |