About Git Branch
Branch Introduction
通常一个仓库会有两个主分支master和develop:
- 主(master)分支
master分支(默认创建的master分支)用来做release - 开发(develop)分支
develop分支用来做日常开发
当软件在develop分支上开发到一定阶段,并通过测试达到稳定阶段的时候,我们会把这个时候develop分支上的软件merge到master(release一个新的版本),然后打上一个tag标记一个版本号
所以我们从来不到master分支上进行开发,master仅仅是用来进行release的,master上永远都是保持最稳定的代码的版本
另外开发过程中还会存在一些临时性分支:
- 功能(feature/xxx)分支
- 预发布(release)分支
- 修补bug(bugfix/xxx)分支
- 紧急bug修复(hotfix/xxx)分支
- 试验(experiment/xxx)分支
为了规范开发和方便维护与溯源,在创建仓库的时候最好是按照一定规范进行Branch命名:
在Git中,分支命名规范并没有统一的标准,但有一些常见的实践可以帮助团队保持一致性和清晰性。
对于master,develop,release等分支一般不存在命名问题,就是固定用这个名字
对于其他分支如下为常见做法:
-
Feature分支:通常以
feature/
开头,后跟功能描述。例如:feature/add_login_page
-
Bugfix分支:可能以
bugfix/
或fix/
开头,后跟错误描述。例如:bugfix/issue_123
-
Hotfix分支:通常以
hotfix/
开头,后跟修复描述。例如:hotfix/urgent_security_issue
-
Release分支:可能以
release/
开头,后跟版本号或发布描述。例如:release/v1.0_
2023_06
-
Experiment分支:如果进行实验性开发,可能以
experiment/
或exp/
开头。例如:experiment/new_algorithm
使用_
(下划线)还是/
(斜杠)来分隔分支名称中的不同部分,取决于团队偏好习惯,要保持统一性(请不要在这种事情上搞创新和个性化):
- 使用
_
(下划线):
-
- 优点:在某些编程环境中,下划线可能更容易阅读和输入。
- 缺点:在URL或路径中,下划线可能与斜杠混淆或不被正确解析。
- 使用
/
(斜杠):
-
- 优点:在URL或文件系统中,斜杠是常见的分隔符,有助于清晰地区分不同层级或部分。
- 缺点:在某些编程环境中,斜杠可能需要转义,这可能会稍微增加复杂性。
关于git分支管理模型有一篇经典文章对此描述非常详细:A successful Git branching model,这篇文章实在太牛逼了竟然有完整翻译版本:介绍一个成功的 Git 分支模型。
Branch Basic Operations
git branch <branch> | 新建分支 |
git checkout –b <branch>
|
新建并切换到新分支 |
git checkout –b <branch> <existingBranch>
|
新建并切换到新分支-基于现有分支 |
git checkout <branch>
|
切换到新分支 |
git branch –a | 查看现有分支 |
git log --graph | 分支图形式查看历史 |
git merge <branch> | 将branch分支merge到当前分支 |
git cherry-pick <commit_id> | 将指定的某次提交(任意分支的任意一次提交)merge到当前分支上来 |
git branch -d <branch> | 删除分支 |
git branch –m <branch> <newName> | 重命名分支 |
Branch Remote Operations
git remote -v | 查看远程仓库地址 |
git remote rm origin
|
删除远程仓库地址 |
git remote add origin url
|
配置远程仓库地址 |
git branch --set-upstream-to=origin/remoteBranchName localBranchName
|
绑定远程分支 |
Merge Branch
比如将develop上更改merge到master上:
$ git checkout master
$ git merge --no-ff develop
这里加上--no-ff非常推介,git merge的默认形式是-ff(fast forward),不会在途中产生Merge branch ‘develop’这个节点,相当于隐藏了部分仓库操作信息,对回溯历史不利。
Merge Specified File
上面讲的是最常规的用法,所有branch都是在开发同一个软件。
但是遇到有的人一个仓库中软件开发到一定阶段就产生了两个分道扬镳的Branch,两个Branch用在不同场景。
两个场景下该软件大部分代码是形同的,然后小部分是不同的,各自有自己的特殊需求,相当于产生了一个额外的定制版本。
本来好的办法是把软件做到兼容两个场景,但是有的时候这样做真很困难;有的时候开发人员水平并不是水平有限,用这种傻瓜方式能满足需求为什么要花心思去设计一个复杂的兼容架构呢。
但是这就出现了一个问题,两个Branch分道扬镳后,有一部分代码是两个branch相同的,如果你在这个branch发现了bug,想要merge到另一个branch会遇到问题,常规的merge操作或者cherry-pick操作是直接合并整个仓库,对于两个branch中各自私有的特性代码我们是不想要合并的。这就提出了将一个branch的制定文件或者文件夹merge到另外一个branch的需求,暂时git不支持这样的merge操作.
但是网友提出了checkout命令来实现这个操作:
如我有一个仓库有两个分支master和newBranch,我想把newBranch中tag vB0.0.2指向的那次提交中 C:\Repo\HelloGit\source\Program.cs这个文件merge到master中
$ git checkout master
$ git checkout <harsh Of vB0,0,2> <file>
但是这种方法实际上是从vB0.0.2那次commit中取出这个文件强行覆盖了当前的这个文件,这样的作法非常危险。
更加安全的做法是(如上图所示):
1. 基于master新建一个名叫masterTemp的hotFix分支
2. 将newBranch给merge到masterTemp上来
在merge过程中或merge后需要做如下处理
- 如果某个文件在master和newBranch中都经过了修改,在merge过程中会产生冲突,自己根据需要保留或丢弃某一个分支的修改即可
- 如果在newBranch上新加了某个文件,则会自动被添加merge后的masterTemp分支上,你需要在merge后查看新添加的文件,如果这些文件是你想要加入到master的则保留;如果这些文件是newBranch中特有的不用加入到master的话你需要进行手动删除
- 如果在newBranch上删除了某个文件,则merge后的masterTemp分支上该文件将会小时,你需要在merge后查看被删除的文件,如果这些文件删除是你想要加入到master的则接受,否则你需要手动从把该文件从之前版本中checkout出来;
3. 将merge并处理后的masterTemp再merge到master上来
4. 删除masterTemp分支
hotFix分支使用完后边不再有存在的价值了
Branch Rename
有时候在仓库创建早期没有很好规划,后期也可以按照如下3步对branch进行重命名
- 切换到想要重命名分支上:
$ git checkout old-branch-name
- 用如下命名在本地重命名:
$ git branch -m new-branch-name
- 更新远程仓库中的分支名:
$ git push origin :old-branch-name new-branch-name
这里old-branch-name是远程分支的旧名称,new-branch-name是新的分支名称。注意,:符号前没有分支名称,表示删除远程的旧分支
Branch Delete
在Git中删除一个branch可以通过如下命令实现:
- 删除本地分支:
$ git branch -d branch_name
- 删除远程分支:
$ git push origin --delete branch_name
fash-forward
recursive
rebase