git checkout -B没有重置或替代方法? [英] git checkout -B without reset or alternatives?

查看:151
本文介绍了git checkout -B没有重置或替代方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用一个可以执行的命令:

  1. 创建新分支(如果不存在).
  2. 检出分支(如果未修改则存在).

当前使用的 git checkout -B分支名称违反了第二个要求,因为如果存在分支,它将分支重置为起始点的 HEAD .您知道结帐/解决方法/可以满足这两个要求的其他命令的任何标志吗?

解决方案

没有一个单独的Git命令可以做到这一点.

我建议使用的命令顺序是:

  git checkout< name> 

其次是 if 失败:

  git checkout -b< name>[<起点]] 

(取决于您想要的行为):

  git checkout [-b< name>] --track<远程跟踪名称> 

其中尖括号中的每个项目表示您要替换的内容(例如,< name> 可能是 feature/fast ),方括号中的每个项目表示所要替换的内容

这里的主要问题是:

  • 如果要创建新的分支名称,则必须选择该新分支名称将标识的提交.您可以通过提供< starting-point> 参数来选择特定的起点;如果您无法命名起点,Git会假设您要 HEAD 作为起点.

    可能还可以选择是否为新分支设置上游设置:这就是-track 的用途.但是,请注意,在某些情况下,会自动暗示-track .

  • 如果您使用的是现有分支名称,则根据上述声明,您不想更改它将确认的提交.(您目前无法选择设置/更改现有分支的上游,这样特定的问题就会消失.)

现在让我们触摸一下这里发生的所有附带问题.

使用 -b git checkout 总是要创建一个新分支

-b 和/或-track 标志告诉 git checkout 它应同时创建新分支,然后切换到该分支.如果切换将失败或确实失败,则应回滚整个操作,而不要完全不创建新分支.所以这里是一个起点.起始点 可以是 HEAD .由于分支是 new ,因此它还没有上游,但是您可以使用告诉 git checkout 将其 set 设置为上游.--track :-track 的参数是上游的名称(应该是本地分支名称,也可以是远程跟踪名称,例如 origin/掌握).

如果提供 -b 标志,则还将提供新的分支名称,因此也就是新分支的名称.如果省略 -b 标志,则必须提供-track 和一个远程跟踪名称:在这种情况下,分支的名称是通过删除远程跟踪部分,例如 origin/feature 变为 feature ,因此 git checkout --track origin/feature 的含义与 git checkout -b功能--track origin/feature .

如果提供起点,Git将需要签出该特定提交.起点名称可以是远程跟踪名称(例如 origin/master origin/feature ),提交哈希ID或其他可以标识犯罪.在大多数情况下,提供远程跟踪名称作为起点等同于提供-track 参数,因此,如果您不想想要设置在上游,添加-no-track .有关完整的说明,请参见 git checkout 文档./p>

没有 -b git checkout 有时仍会创建一个新分支

当您省略 -b 时, git checkout name 将首先测试以查看 name 是否与某些匹配现有分支.如果是这样,那么操作的解码部分就完成了:Git现在尝试检出该特定的提交(由该分支标识),如果成功,则将您的 HEAD 附加到那个分支,这样您现在就在分支上.

但是您可以写,例如:

  git checkout功能/ure 

当您没有一个名为 feat/ure 的分支时.在这种情况下,Git将枚举 all 您的远程跟踪名称,例如 origin/master upstream/master 等.如果在剥离远端部分后恰好一个 feat/ure 相匹配,则Git假定您 meant 可以写:

  git checkout --track origin/feat/ure 

(或其他名称,其中仍包含遥控器).因此,这将创建 feat/ure ,指向相同作为 origin/feat/ure 提交,其中 origin/feat/ure 作为新分支 feat/ure 的上游设置.

如果不存在 feat/ure ,或者不存在,或者存在太多(两个或更多)远程跟踪 feat/ure 样式名称,例如,两者 origin/feat/ure upstream/feat/ure 存在-此 git checkout 只会失败,现在您必须诉诸一个或多个 -b 和/或-track .

另一种选择

如果您不喜欢这些替代方法,则可以 测试分支名称是否存在.为此,请 git rev-parse 转换名称,并在其前面插入 refs/heads/:

  git rev-parse --quiet --verify refs/heads/feat/ure 

如果成功,它将打印出 refs/heads/feat/ure 解析为的哈希ID,并以零状态退出.打印的哈希ID是 feat/ure 分支的尖端,因此存在.如果失败,则不打印任何内容(-quiet --verify )并以非零状态退出,因此 feat/ure 不存在.现在,您可以放心地要求 create feat/ure -即前提是没有其他人潜入您的存储库并创建 feat/ure 当您查看退出状态并确定 feat/ure 不存在(但现在已经存在)时.

在shell脚本中,它变为:

  name = feat/uregit rev-parse --quiet --verify refs/heads/$ name>/dev/null&&存在= true ||存在=假如果$存在;然后git checkout $ name;否则git checkout -b $ name ...其他参数;科幻 

当然,您可以将此脚本转换为Shell别名或实际的Shell脚本,并根据需要进行调用.添加足够的参数解析和错误处理以品尝.

I want to use a command that will do:

  1. Create a new branch if it doesn't exist.
  2. Checkout branch if it exists without any modification to it.

Currently used git checkout -B branchname violates the second requirement because it resets the branch to HEAD of starting point if branch exists. Do you know any flags to checkout / workarounds / another commands that will satisfy both requirements?

解决方案

There's no one single Git command that will do this.

The command sequence I recommend using is:

git checkout <name>

followed by, if that fails:

git checkout -b <name> [<starting-point>]

or (depending on what behavior you want):

git checkout [-b <name>] --track <remote-tracking-name>

where each item in angle brackets represents something you replace (e.g., <name> might be feature/fast) and each item in square brackets represents something that is optional.

The main issue here is this:

  • If you are creating a new branch name, you must choose which commit this new branch name will identify. You choose a specific starting point by supplying a <starting-point> argument; if you fail to name a starting-point, Git will assume you want HEAD as the starting point.

    You may also choose whether the new branch should have an upstream set: that's what the --track is for. However, note that in some cases, --track is implied automatically.

  • If you are using an existing branch name, you—per your statement above—do not want to change which commit it will identify. (You do not, at this time, have the option of setting / changing the upstream for the existing branch, so that particular question drops out of the picture.)

Let's now touch on all the side issues that happen here.

With -b, git checkout always wants to create a new branch

The -b and/or --track flag tells git checkout that it should both create the new branch and then switch to it. If the switching-to will or does fail, it should roll back the entire operation and not create the new branch after all. So here there is a starting-point. The starting-point may be HEAD. Because the branch is new, it does not yet have an upstream, but you can tell git checkout to set an upstream, using --track: the argument to --track is the name of the upstream (which should be either a local branch name, or a remote-tracking name such as origin/master).

If you supply the -b flag, you also supply the new branch name, and that is therefore the new branch's name. If you omit the -b flag, you must have provided --track and a remote-tracking name: in that case, the branch's name is the name produced by removing the remote-tracking part, e.g., origin/feature becomes feature, so git checkout --track origin/feature means the same thing as git checkout -b feature --track origin/feature.

If you supply a starting-point, Git will need to check out that specific commit. The starting-point name can be a remote-tracking name (such as origin/master or origin/feature), or a commit hash ID, or anything else that identifies a commit. In most cases, supplying a remote-tracking name as a starting-point is equivalent to supplying the --track argument as well, so if you don't want to set an upstream, add --no-track. See the git checkout documentation for a complete description.

Without -b, git checkout still sometimes creates a new branch

When you leave out -b, git checkout name will first test to see if name matches some existing branch. If so, the decoding part of the operation is done: Git now tries to check out that particular commit (identified by that branch) and if that succeeds, attaches your HEAD to that branch, so that you're now on the branch.

But you can write, e.g.:

git checkout feat/ure

when you do not have a branch named feat/ure. In this case, Git will enumerate all your remote-tracking names, such as origin/master, upstream/master, and so on. If exactly one matches feat/ure after stripping off the remote part, Git assumes that you meant to write:

git checkout --track origin/feat/ure

(or whatever the name is with the remote still in it). Hence this will create feat/ure, pointing to the same commit as origin/feat/ure, with origin/feat/ure as the upstream setting of the new branch feat/ure.

If no feat/ure exists and either there are either no, or too many (two or more) remote-tracking feat/ure style names—e.g., both origin/feat/ure and upstream/feat/ure exist—this git checkout will simply fail, and now you must resort to one or more of -b and/or --track.

Another alternative

If you don't like these alternatives, it is possible to test whether a branch name exists. To do so, ask git rev-parse to translate the name, with refs/heads/ inserted in front of it:

git rev-parse --quiet --verify refs/heads/feat/ure

If this succeeds, it prints out the hash ID to which refs/heads/feat/ure resolves, and exits with a zero status. The printed hash ID is the tip of the feat/ure branch, which therefore exists. If this fails, it prints nothing (--quiet --verify) and exits with a nonzero status, so feat/ure does not exist. You can now safely ask to create feat/ure—that is, provided that no one else has snuck in to your repository and created feat/ure while you were looking at the exit status and determining that feat/ure did not exist (but now does).

In a shell script, this becomes:

name=feat/ure
git rev-parse --quiet --verify refs/heads/$name >/dev/null && exists=true || exists=false
if $exists; then git checkout $name; else git checkout -b $name ...additional arguments; fi

and of course you can turn this script into a shell alias or actual shell script, calling it whatever you like. Add sufficient argument parsing and error handling to taste.

这篇关于git checkout -B没有重置或替代方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆