【问题标题】:Create/Push new local branch to repository based on remote基于远程创建/推送新的本地分支到存储库
【发布时间】:2022-01-08 03:13:14
【问题描述】:

谁能告诉我我的行为有什么问题?我正在尝试从远程分支创建一个新分支,并将新分支推送到我的存储库。

Description:
-Currently on branch "test"
-git pull
-git checkout -b <new_branch_name> origin/test

我确认我的分支已切换到新分支。但是,当我通过 Visual Studio 提交/推送我的更改时,并未创建新分支,而是将更改推送到远程“origin/test”。

相反,如果我在没有第二个参数“origin/test”的情况下运行 checkout 命令(当前仍在 origin/test 分支上),然后执行 git push,我的新分支就会创建

为什么会这样?

【问题讨论】:

    标签: git visual-studio github version-control git-push


    【解决方案1】:

    TL;DR

    这是因为您的新分支的上游设置为origin/test。 Visual Studio 显然(错误)使用它来决定要求远程更新其test 分支。

    重要背景

    分支不是从分支创建的。分支是从 commits 创建的。了解和理解这一点很重要;如果你认为分支在 Git 中意味着什么,你最终会伤害自己。这就像假设 1980 年代的汽车具有自动驾驶能力。

    上游

    也就是说,在 Git 中,每个分支可以有一个 upstream 集。一个分支要么有上游集,要么没有上游集。要设置特定的上游,请使用git branch --set-upstream-to:

    git branch --set-upstream-to=origin/somebranch
    

    例如。当前分支现在将origin/somebranch 设置为其上游(除非命令失败,在这种情况下没有任何改变)。如果之前将 origin/otherbranch 设置为上游,则该上游现在被移除,因为只能设置一个上游:origin/somebranch 现在是上游。

    要取消上游,使用git branch --unset-upstream:

    git branch --unset-upstream
    

    当前分支现在没有上游。如果之前没有上游,这个操作什么也不做;否则,它会删除上游设置。

    一个分支的上游是:

    • 另一个(本地)分支名称,或
    • 远程跟踪名称,例如 origin/somebranch。

    在命令行 Git 中,git push 的行为(没有其他参数)由push.default 设置控制。如果将其设置为simple——就像今天一样——这种git push只会推送到当前分支的上游,并且只有当上游设置为远程跟踪名称时——一旦远程部分被移除——匹配当前分支。

    例如,假设当前分支名为br1,并且origin/br1 和origin/br2 都存在。如果我们运行:

    git branch --set-upstream-to=origin/br2
    git push
    

    我们将收到来自git push 的错误,因为origin/br2 中的名称br2 与名称br1 不匹配。但是,如果我们再运行:

    git branch --set-upstream-to=origin/br1
    git push
    

    git push 这次将调用 origin 并尝试让位于 origin 的 Git 存储库更新其他 Git 存储库的分支 br1(我们在本地记得的另一个 Git 上的分支为 @ 987654348@)。

    分支创建和上游设置

    当我们选择创建一个新分支时——使用git branch、git checkout -b 或git switch -c——我们必须给 Git 两件事:

    1. Git 需要它应该创建的新分支的名称。
    2. Git 需要一些现有提交的哈希ID。新创建的分支将指向这个现有的提交。

    默认哈希ID,如果我们不给Git一个,就是当前提交的哈希ID(由当前分支名 在大多数情况下)。也就是说,如果我们运行了git checkout test,那么当前分支名称是test,我们运行:

    git rev-parse test
    

    和

    git rev-parse HEAD
    

    我们将从两个操作中获得相同的哈希 ID。这是因为特殊名称HEAD 附加到分支名称test,而分支名称test 指向其哈希ID 都为git rev-parse 命令打印的提交。

    我们可以像这样绘制这个设置:

    ... <-F <-G <-H   <-- test (HEAD)
    

    也就是说,nametest指向一些带有一些哈希 ID 的提交,这里绘制为 H,代表“哈希”。 Git 中的每个提交都有快照和元数据,提交中的元数据包含以前提交哈希 ID 的列表,通常只有一个条目长。在这种情况下,commit H 包含一些较早提交的哈希 ID——即“指向”——我们只是调用其哈希 ID G。 (在每种情况下,真正的哈希 ID 都是一些看起来很丑的随机字母和数字字符串。)提交 G 有一个快照和元数据,因此指向更早的提交 F,它有一个快照和元数据等等。

    当我们要求 Git 创建一个 新 分支名称时,在这种情况下使用 git checkout -b newbr,Git 将:

    1. 创建新名称,指向选定的提交——在本例中为提交H——然后
    2. 将HEAD 附加到新名称。

    我们可以画出这样的结果:

    ... <-F <-G <-H   <-- newbr (HEAD), test
    

    也就是说,两个分支名称都指向同一个提交(其哈希 ID 为 H)。

    当我们使用这种形式的分支创建时,新分支没有上游集。所以newbr 有没有上游。命令行git push 会在现代 Git 中使用默认值,给我们一个错误;我们将不得不运行git push -u origin newbr 或git push -u origin HEAD 在origin 上创建一个名称newbr,以便我们的Git 将在本地创建origin/newbr,这样我们就有一个origin/newbr 作为上游。 git push 的 -u 选项将立即设置作为上游。

    Visual Studio 显然行为不同。如果没有设置上游,VS 显然只是运行git push origin newbr:newbr,而不是给我们一个错误。

    但是,您可以告诉 Git,在您创建一个分支时,然后设置它的上游。为此,您必须使用通过名称而不是原始哈希 ID 为 Git 提供特定提交的形式:

    git checkout -b newbr origin/test
    

    例如。 这就是你正在做的事情。当你使用git checkout -b 或git switch -c 或git branch 这种形式时,Git 默认会:

    1. 使用名称origin/test 查找提交哈希ID;
    2. 创建指向此提交的新分支名称newbr;和
    3. 将newbr的上游设置为origin/test。

    请注意这个额外的步骤 3,当使用 git checkout -b newbr 而不使用该额外参数时,不会发生。

    在命令行 Git 中,这个选择——创建一个新的分支with一个上游集——实际上可以通过多个选项来控制:

    • -t 或 --track 选项表示做这样做。
    • --no-track 选项表示不要这样做。
    • 配置设置branch.autoSetupMerge 表示是否执行此操作,在这种情况下,当未指定-t 或--no-track 时。

    我上面给出的描述涵盖了branch.autoSetupMerge 未设置 或设置为true 时的正常行为。您可以将其设置为false,在这种情况下,分支创建选项始终如同指定了--no-track,您可以将其设置为always,这使得Git 将本地 分支设置为当您提供本地分支名称作为起点时,新分支的上游。

    您可能不应该设置此选项,而只是避免给 git branch 一个起始名称,或者使用 --no-track 选项:

    git checkout -b newbr $(git rev-parse origin/test)
    

    或:

    git checkout -b newbr --no-track origin/test
    

    这两种方法都将避免为新分支设置任何上游。

    【讨论】:

    • 非常感谢您抽出宝贵时间撰写如此深入的描述 - 我确实学到了一些东西
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-10
    • 2015-04-14
    • 2011-01-09
    • 2011-02-15
    • 2011-10-15
    • 1970-01-01
    相关资源
    最近更新 更多