我有两个分支:master和dev

我想从开发分支创建一个“功能分支”。

目前在分支开发中,我做到了:

git checkout -b myfeature dev

…(一些工作)

git commit -am "blablabla"
git push origin myfeature

但是,在想象我的树枝之后,我得到了:

--**master**
------0-----0-----0-----0-----0
------------------------**dev**----**myfeature**

我的意思是分支似乎很快就合并了,我不明白为什么。。。

我做错了什么?

如何从另一个分支分支并将其推回到功能分支的远程存储库?

所有这些都在一个分支模型中,就像这里描述的那样。


当前回答

如果您想从Git中的任何现有分支创建一个新分支,只需遵循以下选项即可。

首先从要创建新分支的位置更改/签入分支。例如,如果您有以下分支,如:

主人开发分支1

因此,如果要在名为“branch1”的分支下创建名为“subbranch_of_b1”的新分支,请执行以下步骤:

签出或更改为“branch1”git结帐分支1现在,使用以下命令在“branch1”下创建名为“subbranch_of_b1”的新分支。git checkout-b subbranch_of_b1分支1上面的命令将在branchbranch1下创建一个名为subbranch_of_b1的新分支(注意,上面命令中的branch1不是强制性的,因为HEAD当前指向它,但是如果您在不同的分支上,则可以精确到它)。现在,在使用subbranch_of_b1之后,您可以在本地或远程提交、推送或合并它。

将subbranch_of_b1推到远程:

 git push origin subbranch_of_b1

其他回答

如果您想从Git中的任何现有分支创建一个新分支,只需遵循以下选项即可。

首先从要创建新分支的位置更改/签入分支。例如,如果您有以下分支,如:

主人开发分支1

因此,如果要在名为“branch1”的分支下创建名为“subbranch_of_b1”的新分支,请执行以下步骤:

签出或更改为“branch1”git结帐分支1现在,使用以下命令在“branch1”下创建名为“subbranch_of_b1”的新分支。git checkout-b subbranch_of_b1分支1上面的命令将在branchbranch1下创建一个名为subbranch_of_b1的新分支(注意,上面命令中的branch1不是强制性的,因为HEAD当前指向它,但是如果您在不同的分支上,则可以精确到它)。现在,在使用subbranch_of_b1之后,您可以在本地或远程提交、推送或合并它。

将subbranch_of_b1推到远程:

 git push origin subbranch_of_b1

在开发分支上同时执行工作。在您的场景中,功能分支从开发分支的顶端向前移动,但开发分支不会改变。画直线更容易,因为它可以被认为是向前运动。您到达了dev上的A点,从那里开始,您只需沿着一条平行路径继续。这两个分支并没有真正分开。

现在,如果您在合并之前对dev进行提交,您将再次从同一个提交a开始,但现在功能将转到C,而dev转到B。这将显示您正在尝试可视化的拆分,因为分支现在已经分叉。

*-----*Dev-------*Feature

       /----*DevB
*-----*DevA
       \----*FeatureC

要从另一个分支创建分支,也可以使用以下语法:

git push origin refs/heads/<sourceBranch>:refs/heads/<targetBranch>

它比“git checkout-b”+“git push origin”略短

创建分支

签出主分支时创建分支。此处,master中的提交将同步到您创建的分支。git分支1签出branch1时创建分支。此处,branch1中的提交将同步到branch2git分支分支2


签出分支

gitcheckout命令切换分支或恢复工作树文件

git签出分支名称


重命名分支

git branch-m branch1 newbranchname


删除分支

gitbranch-d要删除的分支git branch-要删除的D分支(强制删除而不检查合并状态)


创建和切换分支

git checkout-b branchname


完全包含的分支

git分支--合并



分支差异[git diff branch1..branch2]

多行差异

git diff主机。。分支1

单线差异

git diff—颜色词branch1..branch2

从其他分支在Git中创建分支的各种方法:

这个答案增加了一些额外的见解,这些见解在现有答案中还没有,只是关于问题本身的标题(从另一个分支在Git中创建分支),但没有解决问题的更窄的细节,这里已经有了足够的答案。

我添加这个是因为我真的需要知道如何做下面的第一项(从一个我没有签出的分支创建一个新分支),但如何做并不明显,谷歌搜索导致了这里的搜索结果。所以,我将在这里分享我的发现。这里的任何其他答案都没有很好地触及到这一点。

在这里,我还将添加我在常规工作流中使用的其他最常见的git分支命令,如下所示。

1.要从尚未签出的分支创建新分支,请执行以下操作:

当您签出任何分支时,从branch1创建branch2(例如:假设您签出了master):

git branch branch2 branch1

一般格式为:

git branch <new_branch> [from_branch]

man git分支显示如下。我称之为<new_branch>的是他们所称的<branchname>,而我所称的[from_branch]是他们所说的[<start point>]:

git分支[--track |--no track][-l][-f]<branchname>[<start point>]

2.要从已签出的分支创建新分支,请执行以下操作:

git branch new_branch

这非常适合在重新定基、挤压、硬重置等之前进行备份,或者在做任何可能严重破坏分支的事情之前进行备份。

示例:我正在使用feature_branch1,我将使用gitrebase-I master将20个提交压缩为1个。万一我想“撤销”这个,让我们先备份这个分支!我做这一切。。。这个。。。时间到了,我发现我总是可以很容易地回到这个备份分支并重新分支,以防我在这个过程中搞乱了feature_branch1,这是非常有用和令人欣慰的:

git branch feature_branch1_BAK_20200814-1320hrs_about_to_squash

20200814-1320hrs部分是YYYYMMDD HHMMhrs格式的日期和时间,即2020年8月14日13:20(下午1:20)。这样,我就可以很容易地找到备份分支,直到我确定可以删除它们。如果你不这样做,而且你搞砸了,你必须在搞砸之前使用git reflog来找到你的分支,这会更加困难,压力更大,更容易出错。

感叹:关于git checkout与git switch的注释

经典的通用“瑞士军刀”,可以做1000件事:数字结账。git checkout的新的和实验性的替代命令:git switch+git restore。

git开关是最近在Gitv2.23中添加的。使用git--version查看您的git版本。它被设计成一种非常有限的git签出形式,只用于切换分支,而不是像git签入那样也能够签出或恢复文件。在这里阅读更多信息:https://www.git-tower.com/learn/git/commands/git-switch.

另请参阅:在引入git开关后,git结账仍然做什么?。gitrestore提供了git开关不包含的git checkout的一些其他功能。

手动开关和手动恢复警告:

这个命令是实验性的。行为可能改变。

所以,如果你愿意,可以继续使用git结账。它的行为不太可能改变。

我自己基本上只使用git签出,但如果您愿意,欢迎使用git开关(以及git还原来还原或“签出”文件)。

3.要从已签出的分支创建并签出新分支,请执行以下操作:

# the standard, "classic" command most people still use; `-b` stands
# for "create 'b'ranch"
git checkout -b new_branch

# the newer, "experimental" command now available as of Git v2.23; `-c` stands
# for "'c'reate branch"
git switch -c new_branch

为了清楚地了解那里发生了什么,请知道上面的一个命令相当于这两个单独的命令:

# classic
git branch new_branch
git checkout new_branch

# OR: new/experimental as of Git v2.23
git branch new_branch
git switch new_branch

4.要从尚未签出的分支创建并签出新分支,请执行以下操作:

# classic
git checkout -b new_branch from_branch

# OR: new/experimental as of Git v2.23
git switch -c new_branch from_branch

为了清楚地了解那里发生了什么,请知道上面的一个命令相当于这三个单独的命令:

# classic
git checkout from_branch
git branch new_branch
git checkout new_branch

# OR: new/experimental as of Git v2.23
git switch from_branch
git branch new_branch
git switch new_branch

5.重命名分支

就像重命名终端中的常规文件或文件夹一样,git认为“重命名”更像是一个'm've命令,因此您可以使用gitbranch-m重命名分支。以下是一般格式:

git branch -m <old_name> <new_name>

man git分支显示如下:

git分支(-m |-m)[<oldbranch>]<newbranch>

示例:让我们将branch_1重命名为branch_1.5:

git branch -m branch_1 branch_1.5

或者,如果您已经签出了branch_1,则可以将当前签出的分支重命名为branch_1.5,如下所示:

git branch -m branch_1.5

6.当您当前已签出feature1时,要根据main上最新的上游更改创建新的feature分支(feature2)

让我们把上面学到的很多东西放在一起,以展示一个非常常见的示例,每当我们完成一个功能并需要启动另一个功能时,我们都需要运行该示例。

# The beginner/intermediate way

git checkout main           # check out main branch
git pull                    # pull latest upstream changes down
git checkout -b feature2    # create branch `feature2` from `main`, and check
                                # it out, all in one step`

# The advanced way

# [this is what I do--I'll explain why, below]
git fetch origin main:main      # pull latest upstream changes down from the
                                    # remote `main` branch, to the
                                    # locally-stored remote-tracking **hidden**
                                    # branch named `origin/main`, **and** to
                                    # the local `main` branch
git checkout -b feature2 main   # create branch `feature2` from `main`, and
                                    # check it out, all in one step`

# OR (nearly the same thing)
git fetch origin main           # pull latest upstream changes down from the
                                    # remote `main` branch, to the
                                    # locally-stored remote-tracking **hidden**
                                    # branch named `origin/main`. This does NOT
                                    # update the local `main` branch though!
git checkout -b feature2 origin/main # create branch `feature2` from
                                        # `origin/main`, and check it out, all
                                        # in one step`

所以,当我正在进行分支功能1,并且刚刚完成它,并准备开始基于最新主分支的新功能2时,我为什么要这样做:

git fetch origin main:main
git checkout -b feature2 main

…而不是这样?:

git checkout main
git pull
git checkout -b feature2

令人惊讶的是,答案是git结账可能是一个非常缓慢和繁重的操作-在使用回购的.git/hook/post checkout文件中的git lfs签出后挂钩的大型单体回购上,最多需要3个多小时。让我解释一下。git/hooks/post-checkout文件是一个可执行文件,包含git每次运行git checkout后都会运行的脚本。如果它包含对git lfs签出后“$@”的调用,那么在运行一个看起来无辜的git签出后,它可能会尝试下载20+GB的git lfs数据(特定于我在您的场景中工作的回购)。我不想那样做!因此,我跳过了git结账流程,避免了麻烦,立即开始使用我的feature2分支,而不用先下载所有我不需要的东西!

另请参见:

快速链接到我经常引用的答案,并认为是“git基础知识”:从另一个分支在git中创建分支的各种方法有关在git中签出文件或目录的所有信息根据Git,谁是“我们”?谁是“他们”?如何通过--diff过滤器使用gitdiff过滤器=如何将git-lfs用作基本用户:git-lfs-fitch、git-lfsfetch-all和git-lfspull之间有什么区别?