从另一个分支创建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
的说明
- 可以做1000件事情的经典通用 "瑞士军刀":
git checkout
。
- 替代命令
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 switch
和man git restore
都警告道:
该命令是实验性的,行为可能会更改。
所以,如果你喜欢的话,可以继续使用git checkout
。它的行为不太可能改变。
我基本上只使用git checkout
,但如果你愿意,你可以使用git switch
(和git restore
来还原或"检出"文件)。
3. 从您已经检出的分支创建一个新的分支,并检出它:
git checkout -b new_branch
git switch -c new_branch
为了让那里发生的事情更加明显,知道这个命令相当于这两个单独的命令:
git branch new_branch
git checkout new_branch
git branch new_branch
git switch new_branch
4. 从一个未被检出的分支创建并检出一个新分支:
git checkout -b new_branch from_branch
git switch -c new_branch from_branch
为了让那里发生的事情更加明显,知道这个命令等同于这三个单独的命令:
git checkout from_branch
git branch new_branch
git checkout new_branch
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
)
让我们将上面学到的大部分内容结合起来,呈现一个非常常见的示例,每当我们完成一个功能并需要开始另一个功能时,我们需要运行它。
git checkout main
git pull
git checkout -b feature2
git fetch origin main:main
git checkout -b feature2 main
git fetch origin main
git checkout -b feature2 origin/main
所以,当我在分支
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
分支,而不必先下载所有那些我不需要的东西!
另请参阅:
- 快速链接到我经常引用并认为是“git 基础知识”的答案:
- 各种从其他分支创建分支的方法
- 关于在 git 中检出文件或目录的全部内容
- 根据 Git,"我们"和"他们"是谁?
- 如何通过 --diff-filter= 使用
git diff
过滤器
- 如何作为基本用户使用
git lfs
:git lfs fetch、git lfs fetch --all 和 git lfs pull 之间有什么区别?