Git 分支管理
Git 分支
Git 保存的不是文件的变化或者差异,而是一系列不同时刻的文件快照。在进行提交操作时,Git 会保存一个提交对象(commit object),该提交对象包含:
- 一个指向暂存内容快照的指针
- 作者的姓名和邮箱
- 提交信息
- 指向父对象的指针
- 首次提交产生的提交对象没有父对象
- 普通提交操作产生的提交对象有一个父对象
- 多个分支合并产生的提交对象有多个父对象
Git 的分支本质上是包含所指提交对象校验和(长度为 40 的 SHA-1 值字符串)的文件,所以分支的创建和销毁都异常高效。创建一个新分支就像是往一个文件中写入 41 个字节(40 个字符和 1 个换行符)。
Git 的默认分支名字是 master
,git init
命令默认创建 master 分支, master 分支并不是一个特殊分支, 它跟其他分支完全没有区别。可以通过 init.defaultBranch
参数修改默认分支名称,目前新版本的 Git 以及 GitHub 都使用 main
作为默认分支名称,如果你的默认分支名称不是 main 的话,可以通过如下命令修改默认分支名称为 main
:
1git config --global init.defaultBranch main
本地分支管理
查看分支
使用不带参数的 git branch
命令查看所有分支的列表:
1git branch
有 *
标记的分支是 HEAD
当前所指分支。
查看每个分支的最后一次提交:
1git brach -v
查看已经合并或未合并到当前分支的分支:
1git branch --merged
2git branch --no-merged
查看提交历史,各个分支点指向以及项目的分支分叉情况:
1git log --oneline --decorate --graph --all
创建分支
使用 git branch
命令创建一个新的分支,但是不会自动切换到新分支中去,该命令实际上只是创建了一个可以移动的指针,该指针指向 HEAD
指针指向的提交对象。
1git branch <branch-name>
Git 通过一个特殊指针 HEAD
来指示当前所在的本地分支。
可以使用 git log
命令查看各个分支当前所指的对象:
1git log --oneline --decorate
切换分支
使用 git checkout
命令切换到一个已经存在的分支:
1git checkout <branch_name>
该命令做了两件事:
- 使 HEAD 指针指向相应的分支。
- 将工作目录恢复成相应分支所指向的快照内容。
使用带 -b
参数的 git checkout
命令来新建分支并同时切换到该分支上:
1git checkout -b <branch_name>
切换为上一个分支:
1git checkout -
Note:
- 切换分支会改变工作目录中的文件。
合并分支
使用 git merge
命令合并指定分支到当前分支:
1git merge <branch-name>
删除分支
使用带 -d
选项的 git branch
命令删除分支:
1git branch -d <branch-name>
使用该命令删除未合并的分支时会失败,可以使用带 -D
选项强制删除该分支:
1git branch -D <branch-name>
远程分支管理
远程引用是对远程仓库的引用(指针),包括分支、标签等。
可以通过 git ls-remote <remote>
来显式地获得远程引用的完整列表,或者通过 git remote show <remote>
获得远程分支的更多信息。
远程跟踪分支是远程分支状态的引用,它们以 (remote)/(branch)
形式命名
Note
- 远程仓库名字 origin 与分支名字 master 一样,在 Git 中并没有任何特殊含义。
- master 分支是运行
git init
命令时的默认分支名字。 - origin 是运行
git clone
命令是默认的远程仓库名字。 - 运行
git clone -o <name>
可以修改远程仓库名字。
- master 分支是运行
如果要同步你的工作,运行 git fetch origin
命令,该命令会查找 origin 在哪一个服务器上,并从中抓取本地没有的数据,并且更新本地数据,移动 origin/master
指针指向新的、更新后的位置。
运行 git remote add
命令添加一个新的远程仓库引用到当前的项目
推送分支
当你想要公开分享一个分支时,需要将其推送到有写入权限的远程仓库上。
本地的分支并不会自动与远程仓库同步 - 你必须显式地推送想要分享的分支。这样,你就可以把不愿意分享的内容放到私人分支上,而将需要和别人 协作的内容推送到公开分支。
将当前分支推动到远程仓库 <remote>
中的 <branch>
分支上:
1git push <remote> <branch>
追踪远程分支
跟踪分支是与远程分支有直接关系的本地分支。
如果在一个跟踪分支上输入 git pull
,Git 能自动地识别去哪个服务器上抓取、合并到哪个分支。
当克隆一个仓库是,它通常会自动地创建一个跟踪 origin/master
分支的 master
分支。
1git checkout -b <branch> <remotename>/<branch>
2git checkout --track origin/serverfix
如果想要将本地分支与远程分支设置为不同名字,你可以轻松地增加一个不同名字的本地分支的上一个命令:
1git checkout -b sf origin/serverfix
查看设置的所有跟踪分支:
1git branch -vv
2
3git fetch --all; git branch -vv
删除远程分支
使用带有 --delete
参数的 git push
命令删除远程分支,格式如下:
1git push <remote> --delete <branch-name>
例如,删除 origin 远程仓库中的 fixbug 分支:
1git push origin --delete fixbug
变基
在 Git 中整合来自不同分支点修改主要有两种方法:merge
和 rebase
。这两种整合方法没有任何区别,但是变基使得提交历史更加整洁。
一般我们这样做的目的是为了确保在向远程分支推送时能保持提交历史的整洁。例如向某个别人维护的项目贡献代码时,你首先在自己的分支里进行开发,当开发完成时你需要先将你的代码变基到 origin/master
上,然后再向主项目提交修改。这样的话,该项目的维护者就不再需要进行整合工作,只需要快进合并便可。
保存与恢复现场
git stash
git stash pop
git stash apply stash@{id}
git stash drop stash@{id}
多人协作
- 查看远程库信息:
git remote -v
- 本地新建的分支如果不推送到远程,对其他人就是不可见的
- 从本地推送分支使用
git push origin branch-name
,如果推送失败,先用git pull
抓取远程的新提交 - 在本地创建和远程分支对应的分支,使用
git checkout -b branch-name origin/branch-name
,本地和远程分支的名称最好一致 - 建立本地分支和远程分支的关联,使用
git branch --set-upstream branch-name origin/branch-name
- 从远程抓取分支,使用
git pull
,如果有冲突,要先处理冲突