从另一个分支创建一个分支而不跟踪它

Create a branch from an other branch without tracking it

通常,我会这样创建一个分支:

git checkout branch
git checkout -b new_branch

它运行良好,因为它不会自动设置上游分支,所以它向我显示了推送设置上游的警告。我通常复制粘贴它然后它正确地跟踪远程分支...

这么说很麻烦...

所以我开始使用一种新的方法来减少步骤:

git checkout -b new_branch from_branch

不幸的是,它给了我这个输出:

git checkout -b xxx origin/staging
Branch xxx set up to track remote branch staging from origin.
...

所以当我尝试推送时,它给了我这个错误:

fatal: The upstream branch of your current branch does not match

显然上游不是我想要的...我宁愿让它自动添加 origin/xxx 或根本没有上游。

我看到有一个“--no-track”选项;有没有办法让它成为默认值?我没有成功使用 track 选项。

it works well because it doesn't automatically set an upstream branch

你既对又错。怎么可能?
嗯,这取决于你 git 版本。
Git 版本 1.X 的工作方式与 git v2.X 不同。

你的上游依赖于你用来创建分支的 git 版本。如果您使用 1.X 并创建了一个分支,然后更新了您的 git 版本并创建了一个新分支,那么它们的行为将有所不同。

您始终可以手动编辑 .git/config 文件以查看您的跟踪分支。 git remote -v 会将它们打印到您的屏幕上。

git release notes 2.0

https://git.kernel.org/cgit/git/git.git/tree/Documentation/RelNotes/2.0.0.txt

When git push [$there] does not say what to push, we have used the traditional matching semantics so far (all your branches were sent to the remote as long as there already are branches of the same name over there).

In Git 2.0, the default is now the simple semantics,


你可以做什么?

如您所见,--no-track 选项将创建一个没有上游的分支。

另一种选择:

您可以创建一个孤立分支(没有历史记录的分支),然后使用 cherry-pick 向其中添加所有需要的历史记录。

git checkout --orphan <new_branch> [<sha-1>]

现在您将清空历史记录,您可以向其中添加您想要的任何提交。

如您所述,git checkout 命令支持与 git branch 相同的 --track / --no-track 选项,因此要使新分支 zorblatt 指向与 origin/master 相同的 commit,但没有 origin/master 作为其(错误的)上游:

git checkout -b zorblatt --no-track origin/master

遗憾的是,无法默认设置。 (奇怪的是,一个git-guigui.matchTrackingBranch的配置旋钮。)

(旁白:旧动词,track,有点糟透了:"branch X tracks remote-tracking branch Y/Z" 很快 "branch" 和 "track" 这两个词似乎不再意味着 任何东西."Have as upstream"笨手笨脚的,但至少不是从冗余系出来的。)

tl;dr:您可能想做 git config --global push.default=upstream,但是对于 git push 将执行的确切操作还有其他设置可能更适合您的工作流程。


Git 的默认设置一直在进行中。 a bare git push 执行的操作曾经......好吧,它的 C++ 术语是“专家友好”,对于理解的人来说非常有意义,但对于仍然找到腿的人来说是一个惊喜。所以 git 添加了一个 push.default 设置,以及各种“模式”,决定一个 git push 会做什么的方法,找到并最终切换到一些合理的东西,这不会'不要让新手抱怨他们无意中造成的损害。

简而言之,新的 factory-default 行为实际上是一个 child-proof 上限,你必须学会​​克服它,它可以防止粗心的人伤害自己。

如果您阅读 the git push docs,它会暗示所有这些,并指向 git config push.default 的文档:

When the command line does not specify what to push with <refspec> ... arguments or --all, --mirror, --tags options, the command finds the default <refspec> by consulting remote.*.push configuration, and if it is not found, honors push.default configuration to decide what to push (See git-config for the meaning of push.default).

When neither the command-line nor the configuration specify what to push, the default behavior is used, which corresponds to the simple value for push.default: the current branch is pushed to the corresponding upstream branch, but as a safety measure, the push is aborted if the upstream branch does not have the same name as the local one.

the other options are

push.default

Defines the action git push should take if no refspec is explicitly given. Different values are well-suited for specific workflows; for instance, in a purely central workflow (i.e. the fetch source is equal to the push destination), upstream is probably what you want. Possible values are:

  • nothing - do not push anything (error out) unless a refspec is explicitly given. This is primarily meant for people who want to avoid mistakes by always being explicit.

  • current - push the current branch to update a branch with the same name on the receiving end. Works in both central and non-central workflows.

  • upstream - push the current branch back to the branch whose changes are usually integrated into the current branch (which is called @{upstream}). This mode only makes sense if you are pushing to the same repository you would normally pull from (i.e. central workflow).

  • simple - in centralized workflow, work like upstream with an added safety to refuse to push if the upstream branch’s name is different from the local one.

    When pushing to a remote that is different from the remote you normally pull from, work as current. This is the safest option and is suited for beginners.

    This mode has become the default in Git 2.0.

  • matching - push all branches having the same name on both ends. This makes the repository you are pushing to remember the set of branches that will be pushed out (e.g. if you always push maint and master there and no other branches, the repository you push to will have these two branches, and your local maint and master will be pushed there).

    To use this mode effectively, you have to make sure all the branches you would push out are ready to be pushed out before running git push, as the whole point of this mode is to allow you to push all of the branches in one go. If you usually finish work on only one branch and push out the result, while other branches are unfinished, this mode is not for you. Also this mode is not suitable for pushing into a shared central repository, as other people may add new branches there, or update the tip of existing branches outside your control.

    This used to be the default, but not since Git 2.0 (simple is the new default).

--no-track 标志将成为您的朋友。当您使用 checkout 命令而不是 branch 命令创建新分支时,它将实现您不跟踪远程分支的最终目标。

虽然这只为您节省了 3 次击键,但仍然需要输入很多。您可以将其包装在 git 别名中以简化操作,这是我用于此任务的别名:

git config --global alias.nb '!bash -c "git checkout -b  --no-track ${2-origin/master}" -'

它接受 2 个参数并调用 bash 以完成操作。我们使用 branch-per-feature 并且(几乎)总是从 master 开始新分支所以我将第二个参数设为可选并使用 origin/master 作为默认值。

要使用 HEAD 作为默认值,只需将 ${2-origin/master} 更改为 </code>,或替换您自己的分支名称以适合您团队的工作流程。</p> <p>用法:</p> <pre><code>git nb <branch-name> [<source-commit>]