如何在单个操作中创建功能分支并重置为原点/主站?

时间:2016-11-25 09:24:19

标签: git git-branch

我经常以主分支上的小修复开始我的旅程,最终看起来比最初想象的更复杂。

所以我很容易陷入这种情况:

* Damned I have more stuff to check (HEAD -> master)
* Forgot to fix this as well...
* Oops, fixed that too
* Fixed this
* (origin/master)

此时有人要我快速对主分支进行一些小改动。因此,我需要创建一个feature / bugfix分支并将master还原为其origin

$ git branch --magic bug/foobar
$ git log
* Damned I have more stuff to check (HEAD -> bug/foobar)
* Forgot to fix this as well...
* Oops, fixed that too
* Fixed this
* (master, origin/master)

目前我用这个解决了我的问题:

$ git branch bug/foobar
$ git reset --hard origin/master
$ git checkout bug/foobar

我显然可以为它创建一个别名(尚未测试):

swap-to="!git branch $@ && \
          git reset --hard \
             \$(git config --get branch.\$(git rev-parse --abbrev-ref HEAD).remote)/\
             \$(git rev-parse --abbrev-ref HEAD) && \
          git checkout $@"

有更快/更聪明的方法吗?

3 个答案:

答案 0 :(得分:2)

您应该可以将主分支签出为新分支

 $ git checkout origin/master -b feature/new_featur

修改

上述解决方案虽然有效,但它设置新分支以跟踪主分支。 (我不喜欢)

在我继续之前,我通常没有跟踪。

我看了IntelliJ如何检查新分支,这是如何。

$ git checkout origin/master 

在此之后,git会告诉你,你是在一个独立的头上。既然您有一个与origin/master相同的HEAD,请继续检查该提交是否为新分支。

$ git checkout -b feature/new_feature

DON“T FORGET to git fetch

:)魔术伤口,哈?我希望它有所帮助!

答案 1 :(得分:2)

重述问题

在这里,您将开始master,但我们可以选择任何具有上游 U 设置的起始(本地)分支 B 。 (在您的特定情况下,上游是origin/master。)您开始执行一项您认为快速而简单的任务,现在您已经意识到它毕竟不是那么快捷,所以您希望& #34;将其剥离"到它自己的分支。

然后,我们可能会观察到,我们想要的是保存当前分支的名称,然后改变Git"当前分支"的概念。到新创建的分支,指向当前提交,然后调整已保存的分支以指向已保存的分支的上游。

背景

分支名称只是指向某个提交的标签。 Git在这里是相当明智的:git branch允许您创建指向任何现有提交的 new 标签,或移动当前的任何内容分支到任何现有的提交。默认设置是创建指向当前提交的新分支。

棘手的部分是当前分支无法以这种方式移动,原因是当前分支必须与索引和工作树匹配,除了您正在进行的任何活动更改马上。只有一个面向用户("瓷器")命令用于更改Git"当前分支"的概念,即git checkout

幸运的是,git checkout还有-b(创建新分支)标志,其运行方式与git branch非常相似:它默认在当前提交时创建新分支。此外,它避免了尽可能多地触摸索引和工作树 - 就像任何其他git checkout一样 - 所以如果我们在当前提交中创建一个新分支,它永远不必触及索引或工作树所有。结果是它总是成功,并将我们留在新创建的分支上。 (它可以创建一个指向特定提交的新分支,但这也可能失败 - 但我们不需要这个功能,所以我们可以使用它没有的模式&# 39; t失败。好吧,"并没有失败"只要新的分支名称​​ 是新的,至少。)

因此,解决方案

解决方案仍然需要几行脚本,但我们可以将其编写为一个名为git-spinoff的小脚本,并将其放在$ PATH中(我会使用$HOME/scripts/git-spinoff)。我们甚至可以将它作为shell别名函数执行,但我发现脚本通常更好(更容易理解,调试等)。

为了使这个脚本可靠,让我们实际检查我们的必要条件:我们在某个分支上(所以HEAD不是"分离")并且这个branch有一个上游集。然后我们可以创建我们的新分支并使用git branch -f重新点,即不使用git reset - 另一个分支:

#! /bin/sh
#
# git-spinoff: spin the current branch off to a new
# branch.  When this succeeds, we are on the new branch.

die() {
    echo "fatal: $@" 1>&2
    exit 1
}

# check arguments
case $# in
1) newbranch="$1";;
*) echo "usage: git spinoff <newbranch>" 1>&2; exit 1;;
esac

# make sure we are on a branch that has an upstream
branch=$(git symbolic-ref -q --short HEAD) ||
    die "existing branch is detached; there's nothing to restore"
upstream=$(git rev-parse -q --verify @{u}) ||
    die "existing branch $branch has no upstream: there's nowhere to restore-to"

# now create and check out out the new branch, or quit if we can't
git checkout -b "$newbranch" || exit $?

# last, re-adjust the previous branch (which is no longer the current
# branch since we are on the new one we created) to point to its own
# upstream (if this fails, ignore the failure!)
git branch -f "$branch" "$upstream"

最后一个命令实际上可以改进,因为有一个&#34;管道命令&#34;那就是我们想要的。要使用它,我们必须保留原始分支的完整(refs/heads/样式)名称,并选择一条消息。此特定消息可能是可改进的,因此只是一个示例:

fullbranch=$(git symbolic-ref -q HEAD) || die ...
branch=${fullbranch#refs/heads/}
... same as before ...
git update-ref -m \
    "git spinoff: re-point $branch to ${branch}@{upstream}" \
    $fullbranch $upstream

在我们的路径中使用此git-spinoff脚本,我们现在可以运行git spinoff

修改:现在已经过测试,已包含在https://github.com/chris3torek/scripts中(作为https://github.com/chris3torek/scripts/blob/master/git-spinoff)。

答案 2 :(得分:1)

据我所知,只在一个操作中实现这一点的唯一方法就像你说的那样,使用别名,但是为了进行多个操作,我个人预先设置了一个bash函数别名,基本上和别名一样(你在同一个文件中声明它们,但它们看起来更干净,更不易受欢迎。例如:

yourFunction() {
    command1
    command2
      . . .
}

我希望这会有所帮助。