如何在一次操作中创建功能分支并重置为 origin/master?
How to create a feature branch and reset to origin/master in a single operation?
我经常从主分支上的一个小修复开始我的旅程,最终看起来比最初想象的要复杂。
所以我很容易陷入这种情况:
* Damned I have more stuff to check (HEAD -> master)
* Forgot to fix this as well...
* Oops, fixed that too
* Fixed this
* (origin/master)
那时有人让我快速在 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 $@"
有quicker/smarter方法吗?
据我所知,就像你说的那样,在一次操作中实现这一点的唯一方法是使用别名,但是为了进行多次操作,我个人更喜欢 bash 函数别名,基本上与 alias 相同(您在同一个文件中声明它们),但它们看起来更干净且更难以理解。例如:
yourFunction() {
command1
command2
. . .
}
希望对您有所帮助。
您应该可以将 master 分支作为一个新分支签出
$ git checkout origin/master -b feature/new_featur
编辑
上述解决方案在起作用时,将新分支设置为跟踪主分支。 (我不喜欢)
我通常在继续之前取消跟踪。
我查看了 IntelliJ 如何签出新分支,下面是如何。
$ git checkout origin/master
在此之后,git 会告诉您您处于超然状态。现在您有了一个与 origin/master
相同的 HEAD,继续检查该提交作为一个新分支。
$ git checkout -b feature/new_feature
不要忘记到git fetch
:) 魔法伤,哈?我希望它有所帮助!
重述问题
在这里,您从 master
开始,但我们可以选择任何具有上游 U[ 的起始(本地)分支 B =64=]设置。 (在你的特定情况下,上游是 origin/master
。)你开始了一项你认为快速和简单的任务,现在你已经意识到它毕竟不是那么快速和容易,所以你想 "spin it off"到自己的分支。
那么我们可以观察到,我们想要的是保存当前分支的name,然后改变Git的概念"the current branch" 到一个新创建的分支,指向当前提交,然后调整保存的分支指向保存的分支的上游。
背景
分支名称只是指向某个提交的标签。 Git 在这里相当明智:git branch
允许您创建一个 new 标签指向 any 现有提交,或移动任何内容except 任何现有提交的当前分支。默认是创建指向当前提交的新分支。
棘手的部分是 当前分支 不能以这种方式移动,原因是当前分支必须匹配索引和工作树,除了任何您现在正在进行的积极更改。只有一个面向用户的 ("porcelain") 命令可以更改 Git 对 "the current branch" 的概念,即 git checkout
.
幸运的是,git checkout
也有 -b
(创建新分支)标志,它的操作很像 git branch
:它默认在当前提交时创建一个新分支。此外,它尽可能避免触及索引和工作树——就像任何其他 git checkout
一样——所以如果我们在当前提交创建一个新分支,它永远不必触及索引或工作树全部。结果是它总是成功,并将我们留在新创建的分支上。 (它 可以 创建一个指向特定提交的新分支,但这也可能会失败——但我们在这里不需要该功能,因此我们可以使用它不需要的模式不会失败。好吧,"doesn't fail" 只要新分支名称确实 是 至少是新的。)
因此,解决方案
解决方案仍然需要几行脚本,但我们可以将其编写为一个名为 git-spinoff
的小脚本,并将其放入我们的 $PATH(我将使用 $HOME/scripts/git-spinoff
).我们甚至可以将此作为 shell 别名函数,但我发现脚本通常更好(更易于理解、调试等)。
为了使这个脚本可靠,让我们实际检查一下我们需要的条件:我们在某个分支上(所以 HEAD
不是 "detached")并且这个分支有一个上游集合。然后我们可以创建我们的新分支并重新指向——使用 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="";;
*) 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"
最后一个命令实际上可以改进,因为有一个 "plumbing command" 可以做我们想要的。要使用它,我们必须保留原始分支的完整(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 (as https://github.com/chris3torek/scripts/blob/master/git-spinoff)。
我经常从主分支上的一个小修复开始我的旅程,最终看起来比最初想象的要复杂。
所以我很容易陷入这种情况:
* Damned I have more stuff to check (HEAD -> master)
* Forgot to fix this as well...
* Oops, fixed that too
* Fixed this
* (origin/master)
那时有人让我快速在 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 $@"
有quicker/smarter方法吗?
据我所知,就像你说的那样,在一次操作中实现这一点的唯一方法是使用别名,但是为了进行多次操作,我个人更喜欢 bash 函数别名,基本上与 alias 相同(您在同一个文件中声明它们),但它们看起来更干净且更难以理解。例如:
yourFunction() {
command1
command2
. . .
}
希望对您有所帮助。
您应该可以将 master 分支作为一个新分支签出
$ git checkout origin/master -b feature/new_featur
编辑
上述解决方案在起作用时,将新分支设置为跟踪主分支。 (我不喜欢)
我通常在继续之前取消跟踪。
我查看了 IntelliJ 如何签出新分支,下面是如何。
$ git checkout origin/master
在此之后,git 会告诉您您处于超然状态。现在您有了一个与 origin/master
相同的 HEAD,继续检查该提交作为一个新分支。
$ git checkout -b feature/new_feature
不要忘记到git fetch
:) 魔法伤,哈?我希望它有所帮助!
重述问题
在这里,您从 master
开始,但我们可以选择任何具有上游 U[ 的起始(本地)分支 B =64=]设置。 (在你的特定情况下,上游是 origin/master
。)你开始了一项你认为快速和简单的任务,现在你已经意识到它毕竟不是那么快速和容易,所以你想 "spin it off"到自己的分支。
那么我们可以观察到,我们想要的是保存当前分支的name,然后改变Git的概念"the current branch" 到一个新创建的分支,指向当前提交,然后调整保存的分支指向保存的分支的上游。
背景
分支名称只是指向某个提交的标签。 Git 在这里相当明智:git branch
允许您创建一个 new 标签指向 any 现有提交,或移动任何内容except 任何现有提交的当前分支。默认是创建指向当前提交的新分支。
棘手的部分是 当前分支 不能以这种方式移动,原因是当前分支必须匹配索引和工作树,除了任何您现在正在进行的积极更改。只有一个面向用户的 ("porcelain") 命令可以更改 Git 对 "the current branch" 的概念,即 git checkout
.
幸运的是,git checkout
也有 -b
(创建新分支)标志,它的操作很像 git branch
:它默认在当前提交时创建一个新分支。此外,它尽可能避免触及索引和工作树——就像任何其他 git checkout
一样——所以如果我们在当前提交创建一个新分支,它永远不必触及索引或工作树全部。结果是它总是成功,并将我们留在新创建的分支上。 (它 可以 创建一个指向特定提交的新分支,但这也可能会失败——但我们在这里不需要该功能,因此我们可以使用它不需要的模式不会失败。好吧,"doesn't fail" 只要新分支名称确实 是 至少是新的。)
因此,解决方案
解决方案仍然需要几行脚本,但我们可以将其编写为一个名为 git-spinoff
的小脚本,并将其放入我们的 $PATH(我将使用 $HOME/scripts/git-spinoff
).我们甚至可以将此作为 shell 别名函数,但我发现脚本通常更好(更易于理解、调试等)。
为了使这个脚本可靠,让我们实际检查一下我们需要的条件:我们在某个分支上(所以 HEAD
不是 "detached")并且这个分支有一个上游集合。然后我们可以创建我们的新分支并重新指向——使用 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="";;
*) 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"
最后一个命令实际上可以改进,因为有一个 "plumbing command" 可以做我们想要的。要使用它,我们必须保留原始分支的完整(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 (as https://github.com/chris3torek/scripts/blob/master/git-spinoff)。