代码之家  ›  专栏  ›  技术社区  ›  Nishant Florentin

我可以使用相同的命令签出标记和分支吗?

git
  •  0
  • Nishant Florentin  · 技术社区  · 7 年前

    我想编写一个bash函数,将标记/分支签出为具有该名称的分支。有办法吗?

    我尝试了以下方法,但它仅适用于标记,不适用于分支:

    git checkout -b {1} {2}
    

    $ git checkout -b v1.0 v1.0  # works
    $ git checkout -b release release  # fails
    [ fatal: Cannot update paths and switch to branch 'release' at the same time. ]
    $ git checkout -b release origin/release  # works if i prefix origin
    $ git checkout release  # works if i don't give anything
    

    我可以把它合并成一个命令吗?

    0 回复  |  直到 7 年前
        1
  •  2
  •   Nishant Florentin    7 年前

    -B 中描述的方法 mkrieger1's answer 确实有效,但总的来说这不是一个好主意。如果我们创建一个 阴影的名字 标签 名称

    在这种情况下,首先检查各种错误情况可能是最明智的。如果存在这些错误情况,请停止并从某些人员处获得帮助。只有在一切顺利的情况下才能进行。这里,这个 如果一切顺利,继续进行 其他

    git checkout existing-branch 和 git checkout -b new-branch start-point . 在这里 existing-branch 应该 要求 分支 名称同样地 new-branch 变体应该 那个 start-point 做一个 不同的 新分支 那 新分支

    假设您有一些短名称字符串 哪里 可能是 release 或 dev v1.2 或者不管是什么(我们可以假设 s 不是原始散列ID,尽管我们实际上可以测试它)。鉴于此 s

    1. git rev-parse S 生成一些散列ID。 s 是的缩写 refs/heads/ S 是的缩写 refs/tags/ S

      $ git rev-parse stash-exp
      8dbdf339cd2e757143d9f222f662edd8ef745ea8
      

      stash-exp

    2. 或 git版本解析 s 生成一些哈希ID,但失败:

      $ git rev-parse gronk
      gronk
      fatal: ambiguous argument 'gronk': unknown revision or path not in the working tree.
      Use '--' to separate paths from revisions, like this:
      'git <command> [<revision>...] -- [<file>...]'
      

    这种特殊用法 git rev-parse fatal 将上面的消息发送到stderr(您可以通过将stdout和stderr重定向到两个不同的文件来自行测试)。添加 --verify 将其更改为仅投诉(退出非零=失败):

    $ git rev-parse --verify gronk && echo ok || echo failed
    fatal: Needed a single revision
    failed
    

    虽然 git rev-parse --verify stash-exp

    $ git rev-parse --verify stash-exp && echo ok || echo failed
    8dbdf339cd2e757143d9f222f662edd8ef745ea8
    ok
    

    请注意,我们可以使用 git版本解析 告诉我们 引用的错误,或失败:

    $ git rev-parse --verify --symbolic-full-name stash-exp
    refs/heads/stash-exp
    $ git rev-parse --verify --symbolic-full-name gronk
    fatal: Needed a single revision
    

    从这里,我们可以看到 藏匿经验 实际上是一个 分支 v2.1.0 是一个 标签名

    $ git rev-parse --verify --symbolic-full-name v2.1.0
    refs/tags/v2.1.0
    

    这里值得注意的是,有更多的案例 The gitrevisions documentation 具有名称工作的完整列表,包括相关操作: HEAD~3 , master^2~2 --symbolic-full-name 让我们有 git版本解析 告诉我们 名称,然后我们可以将其与我们关心的一个或多个模式进行匹配:

    # check whether $name is a branch name
    hash=$(git rev-parse --verify "$name" 2>/dev/null) || {
        echo "I do not recognize $name at all" 1>&2
        exit 1
    }
    fullname=$(git rev-parse --verify --symbolic-full-name "$name" 2>/dev/null) || {
        echo "I can translate $name to $hash but it is not any branch or tag name" 1>&2
        exit 1
    }
    case "$fullname" in
    refs/heads/*) ;; # ok - it is a branch name
    *)  echo "$name is really $fullname and that is not a branch" 1>&2
        exit 1;;
    esac
    

    因此,上面的代码片段验证了这一点 $name $hash ,以及它的全名 refs/heads/$name $fullname .

    我们为什么关心?

    好吧,关心的一个原因是 git checkout 分支与标记名称的行为不同:

    $ git checkout stash-exp
    Switched to branch 'stash-exp'
    

    自从 藏匿经验 在…上 信息技术

    $ git checkout v2.1.0
    Note: checking out 'v2.1.0'.
    
    You are in 'detached HEAD' state. ... [massive snip]
    

    v2.1.0 不 一个分支,我们在上面 不 现在分店。Git转而切换到这种分离头部模式。

    $ git checkout master
    Previous HEAD position was 6c4ab27f23 Git 2.1
    Switched to branch 'master'
    Your branch is up to date with 'origin/master'.
    

    master ,其中 树枝。因此,我们是否给予,这可能非常重要 分支名称。

    为什么我们更关心

    让我们使用 git checkout -b 分支 那是我的名字 简称 作为我们的 标签 名称

    $ git checkout -b v2.1.0 v2.1.0
    Switched to a new branch 'v2.1.0'
    $ git rev-parse v2.1.0
    warning: refname 'v2.1.0' is ambiguous.
    7452b4b5786778d5d87f5c90a94fab8936502e20
    

    事情是新的,不是吗?让我们创建一个新的虚拟提交:

    $ git commit --allow-empty -m dummy
    [v2.1.0 83429187cf] dummy
    $ git show | sed 's/@/ /'
    commit 83429187cfe0ff9055453b8c2284deabb21139aa (HEAD -> v2.1.0)
    Author: Chris Torek <chris.torek@gmail.com>
    Date:   Sat Feb 23 11:44:29 2019 -0800
    
        dummy
    $ 
    

    我们分支的提示提交是这个新提交, 83429187...

    但是:

    $ git show v2.1.0 | sed -e 's/@/ /' -e 10q
    warning: refname 'v2.1.0' is ambiguous.
    tag v2.1.0
    Tagger: Junio C Hamano <gitster pobox.com>
    Date:   Fri Aug 15 15:09:28 2014 -0700
    
    Git 2.1
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.11 (GNU/Linux)
    
    iQIcBAABAgAGBQJT7oUZAAoJELC16IaWr+bLD3UP/iqk7c+1BdEjIUks3JS8eUu7
    V/sU1dS2K/8ZeeQa9aeqmAxt/9aqeF6DNtN9AcAO5bf2WeGYfKkTdxsb4eWAaw+W
    $ 
    

    名字 v2.1.0 ,有时指 分支 the gitrevisions documentation s 到哈希ID。使用 名称位于使用 名称

    例外情况是命令 知道或假定 他们的论点是错误的 姓名,如 和 git branch . 但这反过来意味着,如果你创造了模棱两可的名字,你会给自己带来麻烦。

    主人 并删除这个不太好的分支名称:

    $ git checkout master
    Switched to branch 'master'
    Your branch is up to date with 'origin/master'.
    $ git branch -D v2.1.0
    Deleted branch v2.1.0 (was 83429187cf).
    

    这就是为什么 git checkout -B release release 这不是一个好计划

    对于 git checkout-B发行版 工作,, 释放 git rev-parse release 必须工作(事实上, git rev-parse release^{commit} 必须工作,尽管我们不需要在这里详细说明)。

    如果 s 释放 或 藏匿经验 s git checkout -B S S 是设置 s s s git checkout S .

    如果它是一个有效的符号名,那么 成为 分支名称,可能是 名称在这种情况下 git签出-B 将创造 git checkout -b S S 这里也是,因为 不是吗 v2.1.0 上面是小写字母 -b 这个选项有效。但这导致了 警告:refname“v2.1.0”不明确 情境:现在我们都有了分支机构 和 标签。如果我们认为这是个坏主意 至少想想,我们根本不应该这么做。

    git签出 带着 现有的 要切换的分支名称 它,否则我们应该使用它 新分支起点 新的 git rev-parse --verify 说 起点 告诉Git要使用什么commit 开始 新的分支,由于它必须解析为实际的提交哈希,因此 不能 与新的分支名称相同:我们确信新名称根本不会解析为任何内容。

        2
  •  2
  •   mkrieger1 djuarezg    7 年前
    $ git checkout -b release release
    

    这意味着:创建一个新分支 release 在 释放 . 因为有一个分支叫 释放

    根据 git签出

    git checkout -b|-B <new_branch> [<start point>]
    

    -b 导致创建一个新分支,就像 吉特分行(1) 我们打了电话,然后退房了。[]

    -B <new_branch> 如果不存在,则创建;否则,它将被重置。这是与

    $ git branch -f <branch> [<start point>]
    $ git checkout <branch>
    

    所以你可以尝试使用 -B 而不是 -b .