从另一个分支在Git中创建一个分支

1663

我有两个分支:masterdev

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

当前在dev分支上,我执行:

git checkout -b myfeature dev

...(某些工作)

git commit -am "blablabla"
git push origin myfeature

可是,当我查看我的分支时,我得到了:

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

我的意思是分支似乎进行了 快进合并,我不明白为什么...

我做错了什么?

如何从另一个分支创建一个分支,并将功能分支推送回远程代码库?

所有这些都是在像这里描述的分支模型中进行的。


请明确一下,您是在问为什么myfeature分支被快进合并,而不是其他形式的合并吗?还是您在问为什么它被合并了?对我来说,后者更有意义,因为我看不到任何合并命令在明显的快进合并观察之前。 - Andres Salas
1
在你的情况下,myfeature 分支只比 dev 分支多了几个提交,所以它被这样显示。它们没有分叉的提交点。一旦 dev 分支有了额外的提交,你将看到它们作为分叉提交的分支,不能简单地快进。 - Sergey P. aka azure
12个回答

2283
如果你喜欢你发布的链接中的方法,可以看一下 Git Flow。这是他为该工作流程创建的一组脚本。但是回答你的问题:
git checkout -b myFeature dev

dev分支创建MyFeature分支。完成工作后再进行操作。

git commit -am "Your message"

现在将你的更改合并到dev分支,但不要使用快进模式

git checkout dev
git merge --no-ff myFeature

现在将更改推送到服务器

git push origin dev
git push origin myFeature

你会以自己的方式看待它。


58
myFeaturedev合并后推送的重要性是什么? - Alexander Suraphel
3
如果 myFeature 分支已经被合并前推送到服务器上,那么就没什么要做的了。但如果 myFeature 分支还没有推送到服务器上,而你希望它出现在服务器中,那么你必须将其单独推送。 - xOneca
37
git checkout -b myFeature dev 和这三个命令:git checkout dev, 然后 git branch myFeature, 最后 git checkout myFeature 一样吗? - Kevin Meredith
4
是的,或者应该是这样。你看到了不同的东西吗? - Abizern
80
为了让其他新手理解,这就是--no-ff合并的效果 - A__
显示剩余13条评论

687

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

首先,切换到您想要创建新分支的分支。例如,如果您有像下面这样的分支:

  • master
  • dev
  • branch1

因此,如果您想在名为"branch1"的分支下创建名为"subbranch_of_b1"的新分支,请按照以下步骤进行操作:

  1. 检出或更改为"branch1"

 git checkout branch1
  • 现在使用以下命令创建名为"subbranch_of_b1"的新分支,在"branch1"下面。

  •  git checkout -b subbranch_of_b1 branch1
    

    以上命令将在分支 branch1 下创建一个名为subbranch_of_b1的新分支(注意,由于HEAD当前指向它,上述命令中的branch1不是必需的,但如果您在不同的分支上,则可以明确它)。

    现在,在处理 subbranch_of_b1 之后,您可以在本地或远程提交、合并或推送它。

    创建另一个分支的示意图

    subbranch_of_b1 推送到远程:

     git push origin subbranch_of_b1
    

    11
    如何将b1的子分支推送到远程? - user269867
    19
    "git push origin subbranch_of_b1" 这条命令可以帮您完成此任务。 - Praveen George
    4
    如果我将更改推送到主分支,那么这些更改会自动出现在branch1中吗? - Master Yoda
    2
    请注意,在上述命令中,branch1并非必需,因为HEAD当前指向它,如果您在不同的分支上,可以明确指定它。这就是我正在寻找的内容。 - felipsmartins
    44
    我来这里想知道 git checkout -b some-branch 是否是 git checkout -b some-branch master 的简写。事实证明,git checkout -b some-branchgit checkout -b some-branch <current_active_branch> 的简写。 - Frank Henard
    显示剩余3条评论

    90

    从另一个分支创建Git分支的各种方法:

    本答案补充了一些关于问题标题(从另一个分支创建Git分支)的额外见解,但不涉及已经有足够答案的更具体问题。

    我之所以添加这个答案,是因为我现在真的需要知道如何执行以下操作1(从我没有检出的分支创建新分支),而这并不明显,谷歌搜索将其作为顶部搜索结果。所以,我将在这里分享我的发现。任何其他答案都没有很好地涉及到这一点,如果有的话。

    顺便说一下,我还会添加我在日常工作流程中使用的其他最常见的git branch命令。

    1. 从你没有检出的分支创建新分支:

    在你检出了任何分支的情况下(例如,假设你已经检出了master),从branch1创建branch2

    git branch branch2 branch1
    

    一般的格式是:

    git branch <new_branch> [from_branch]
    

    man git branch 显示如下。我所说的<new_branch>是他们所说的<branchname>,我所说的[from_branch]是他们所说的[<start-point>]

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

    2. 从当前已检出的分支创建一个新的分支:

    git branch new_branch
    

    这对于在rebase、squash、hard reset等操作之前备份非常有用,防止这些操作严重破坏你的分支。
    例如:我正在feature_branch1分支上,打算使用git rebase -i master命令将20个提交压缩成一个。以防我想要“撤销”这个操作,让我们先备份一下这个分支!我经常这样做,发现它非常有帮助和安心,因为我可以轻松地返回到备份分支,并重新分支尝试再次操作feature_branch1,以防我在此过程中出错。
    git branch feature_branch1_BAK_20200814-1320hrs_about_to_squash
    

    20200814-1320hrs 部分是日期和时间的格式为YYYYMMDD-HHMMhrs,因此这将是2020年8月14日下午1:20时。这样我就有了一种简单的方式来查找备份分支,直到我确定已经准备好删除它们。如果你不这样做并且出现了大问题,你必须使用git reflog找到你在出问题之前的分支,这更困难、更紧张、更容易出错。

    插话:有关 git checkout git switch 的说明

    1. 可以做1000件事情的经典通用 "瑞士军刀": git checkout
    2. 替代命令git checkout的新型实验性命令:git switch+ git restore

    git switch在Git v2.23中最近被添加。使用git --version查看您的git版本。它被设计成一个极其受限的git checkout形式,只设计用于切换分支,而不像git checkout可以检出或还原文件。阅读更多详细信息:https://www.git-tower.com/learn/git/commands/git-switch。

    另请参见:What does git checkout still do after git switch got introduced?git restore提供了一些git switch不包含的git checkout功能。

    man git switchman git restore都警告道:

    该命令是实验性的,行为可能会更改。

    所以,如果你喜欢的话,可以继续使用git checkout。它的行为不太可能改变。

    我基本上只使用git checkout,但如果你愿意,你可以使用git switch(和git restore来还原或"检出"文件)。

    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'ove命令,所以您可以使用git branch -m来重命名分支。以下是一般格式:

    git branch -m <old_name> <new_name>
    

    man git branch 显示如下内容:

    git branch (-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上的最新更改创建一个新的特性分支(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`
    

    所以,当我在分支feature1上时,已经完成了它并准备开始一个新的基于最新的main分支的feature2,我为什么要这样做:
    git fetch origin main:main
    git checkout -b feature2 main
    

    ...而不是这样吗?:

    git checkout main
    git pull
    git checkout -b feature2
    

    答案出乎意料地是,git checkout 可能是一个非常慢且繁重的操作!对于使用 git lfs 后检出钩子在仓库的 .git/hooks/post-checkout 文件上的大型单体仓库,可能需要长达 3 小时以上。让我解释一下。 .git/hooks/post-checkout 文件是一个可执行文件,其中包含一个脚本,每次运行 git checkout 后 git 都会运行它。如果它包含调用 git lfs post-checkout "$@" 的命令,则在运行看似无害的 git checkout 后,它可能会尝试下载特定于仓库(您的情况可能有所不同)的20GB+git lfs 数据。我不想这样做!因此,我跳过了 git checkout 过程,以避免这些麻烦,并立即开始我的 feature2 分支,而不必先下载所有那些我不需要的东西!
    另请参阅:
    1. 快速链接到我经常引用并认为是“git 基础知识”的答案:
      1. 各种从其他分支创建分支的方法
      2. 关于在 git 中检出文件或目录的全部内容
      3. 根据 Git,"我们"和"他们"是谁?
      4. 如何通过 --diff-filter= 使用 git diff 过滤器
      5. 如何作为基本用户使用 git lfs:git lfs fetch、git lfs fetch --all 和 git lfs pull 之间有什么区别?

    3
    最佳答案。其他答案往往会让人感到困惑,因为它们倾向于在创建分支的同时切换到该分支上使用 git checkout - Danijel

    75

    创建分支

    • 在主分支(master)被检出时创建分支。此处将同步主分支(master)中的提交到您创建的分支。

      git branch branch1

    • 在分支(branch1)被检出时创建分支。此处将同步分支(branch1)中的提交到分支(branch2)。 git branch branch2


    检出分支

    git checkout 命令用于切换分支或还原工作区文件。

    • git checkout 分支名

    重命名分支

    • git branch -m branch1 新分支名

    删除分支

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

    创建并切换分支

    • git checkout -b 分支名

    完全包含的分支

    • git branch --merged

    分支差异 [ git diff 分支1..分支2 ]

    多行差异

    • git diff master..branch1

    单行差异

    • git diff --color-words branch1..branch2

    3
    重命名分支后,使用 git push origin :old-name new-name 命令来删除旧的远程分支并推送新的本地分支。 - 95faf8e76605e973

    38

    要在本地目录中从另一个分支创建分支,您可以使用以下命令。

    git checkout -b <sub-branch> branch
    

    例如:

    • 要创建的新分支名称为'XYZ'
    • 分支名称为'ABC',在其下创建'XYZ'
    git checkout -b XYZ ABC
    

    19

    Git 2.23引入了git switchgit restore来拆分git checkout的职责。

    自Git 2.23起,可以从现有分支创建新分支:

    git switch -c my-new-branch

    已切换到新分支'my-new-branch'

    • -c--create的缩写,取代了众所周知的git checkout -b

    请参阅GitHub博客文章,更详细地解释了这些变化:

    Git 2.23为现有命令套件带来了一对实验性命令:git switchgit restore。这两个命令旨在最终为众所周知的git checkout提供更好的接口。新命令打算每个明确分离,整齐地分配git checkout的许多职责。


    13

    同时在dev分支上进行工作。在您的场景中,功能分支从dev分支的末端向前移动,但dev分支不会改变。这可以想象成是向前运动的直线,因此更容易绘制。您已经到达了dev上的A点,然后您只需要沿着平行路径继续前进。这两个分支实际上没有分叉。

    现在,如果您在合并之前在dev上进行提交,您将再次从相同的提交A开始,但现在功能将前往C,而dev则前往B。这将显示您试图可视化的分裂,因为这两个分支现在已经分叉。

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

    对决

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

    12

    如果您想从另一个分支创建一个新分支,那么请按照以下步骤操作:

    假设

    1. 您目前在master分支中。
    2. 您没有要提交的更改。(如果有任何要提交的更改,请将其存储!)
    3. BranchExisting是您需要使用名称BranchMyNew创建新分支的分支名称。

    步骤

    1. 将分支获取到本地计算机。

    2. git fetch origin BranchExisting : BranchExisting
      

    这个命令将在本地创建一个与原有分支同名的新分支。

    1. 现在,从主分支 master 切换到新获取的分支。

    git checkout BranchExisting
    
  • 您现在在BranchExisting分支中。现在从此现有分支创建一个新分支。

  • git checkout -b BranchMyNew
    

    这是给你的!


    5

    这将从当前分支创建新的分支。

    git checkout -b your_new_branch_name 
    

    如果你想要创建已存在的分支的新分支,则可以执行以下操作:
    git checkout -b your_new_branch_name existing _branch_name
    

    1

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

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

    这个命令比 "git checkout -b " + "git push origin " 稍微短一些。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接