Git分支策略
前置知识——远程仓库的使用
git clone
克隆远程仓库,将会创建完整git,包括过去的版本:
git clone https://github.com/schacon/ticgit
git remote
管理远程仓库(每一个url都有一个简称,可以代替整个url)
添加 git remote add simply https://github.com/paulboone/ticgit
查询 git remote -v
显示远程仓库的git以及对应的url
查看远程仓库详细信息,包括当前分支,其他分支的信息,如哪些远程分支不在你的本地,哪些远程分支已经从服务器上移除了, 还有当你执行 git pull 时哪些本地分支可以与它跟踪的远程分支自动合并,git remote show <remote>
重命名 可以修改一个远程仓库的简写名称git remote rename pb paul
删除 一旦你使用这种方式删除了一个远程仓库,那么所有和这个远程仓库相关的远程跟踪分支以及配置信息也会一起被删除。 git remote remove paul
或git remote rm paul
git fetch
抓取数据,可以获得远程仓库中的所有分支的引用,可以随时合并或查看。注,只会下载到本地,不会自动合并或修改,需要手动合并
git pull
如果你的当前分支设置了跟踪远程分支,这个命令可以自动抓取后合并该远程分支到当前分支。
git push
将项目推送到上游,只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。你必须先抓取他们的工作并将其合并进你的工作后才能推送。
git push server master
Git分支
Git每次commit时,对于发生改变的文件,采用的是快照的方式进行保存的,也就是说,每次提交时,只要某文件有发生过改动,Git就会保存一次该文件。
因此,在进行提交时,Git保存的提交的对象中,会包含指向快照的指针,一般是一个树形结构,对应文件结构,包含了指向每一个文件的快照的指针。在保存文件时,还会通过SHA-1哈希算法计算该文件的校验和,一起保存。
当使用 git commit 进行提交操作时,Git 会先计算每一个子目录的校验和, 然后在 Git 仓库中这些校验和保存为树对象。随后,Git 便会创建一个提交对象, 它除了包含上面提到的那些信息外,还包含指向这个树对象(项目根目录)的指针。
提交后,这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针。
相关命令
git branch
分支创建,其实是创建了一个可以移动的新指针,指向某一次提交
git branch testing
Git有一个名为HEAD的特殊指针,指向当前所在的本地分支。
可以通过git log命令查看各个分支指向的提交对象git log --oneline --decorate
删除分支,一般在合并之后使用该命令git branch -d hotfix
,未合并时会失败,可以使用-D选项强制删除。
查看所有分支的列表
git branch
查看每一个分支最后一次提交
git branch -v
过滤已合并或未合并的分支
git branch --merged
git branch --no-merged
git checkout
切换到一个已有的分支,让HEAD指向一个分支 git checkout testing
这条命令做了两件事。一是使 HEAD 指回 master 分支,二是将工作目录恢复成 master 分支所指向的快照内容。
查看分支情况
git log --oneline --decorate --graph --all
git merge
将该分支合并到当前分支
遇到有冲突的合并:
Automatic merge failed; fix conflicts and then commit the result.
冲突文件会包含特殊区段,如
<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html
为了解决冲突,你必须选择使用由 ======= 分割的两部分中的一个,或者你也可以自行合并这些内容。
比如将上面这段换成下面这段:
<div id="footer">contact : email.support@github.com</div>
之后可以运行git status
确定所有文件都已经暂存,然后输入git commit
完成合并提交,可以对默认提交信息进行修改
分支开发工作流
长期分支
维持多个长期分支,每当一个分支的内容稳定后,再将其合并到主分支,也可以设置有不同程度稳定性的分支。
主题分支
对一个问题,可以设置多个主题分支,分别对应某一种解决方案,最后选择某一种。这个一般用来实现某一单一特性或其相关工作。
Git的远程分支
获取远程分支信息,git ls-remote <remote>
和 git remote show <remote>
远程分支一般以 <remote>/<branch>
的形式命名,拉取之后会被保存在本地,但不能修改,只有当再次与服务器连接时,才会更新。
git fetch
更新远程跟踪分支,可以指定远程仓库,如:
git fetch teamone
git push
推送到有写入权限的远程仓库上git push <remote> <branch>
比如git push origin serverfix:awesomebranch
来将本地的 serverfix 分支推送到远程仓库上的 awesomebranch 分支。
从服务器上删除远程分支git push origin --delete serverfix
git merge
抓取的新的远程分支不可修改,可以通过合并,将工作合并到当前所在分支git merge origin/serverfix
,
git checkout
如果想要在子集的分支上工作,可以将其建立在远程跟踪分支之上git checkout -b serverfix origin/serverfix
,这会给你一个用于工作的本地分支,并且起点位于 origin/serverfix。对此,Git 提供了 --track 快捷方式git checkout --track origin/serverfix
,该捷径本身还有一个捷径。 如果你尝试检出的分支 (a) 不存在且 (b) 刚好只有一个名字与之匹配的远程分支,那么 Git 就会为你创建一个跟踪分支:git checkout serverfix
如果想要将本地分支与远程分支设置为不同的名字,你可以轻松地使用上一个命令增加一个不同名字的本地分支:git checkout -b sf origin/serverfix
git branch
想要查看设置的所有跟踪分支,git branch -v
,将会显示每一个分支跟踪的远程分支,以及ahead次数(本地未提交的次数)、behind次数(提交未合并次数)
这个命令并没有连接服务器,它只会告诉你关于本地缓存的服务器数据。 如果想要统计最新的领先与落后数字,需要在运行此命令前抓取所有的远程仓库git fetch --all; git branch -vv
git pull
含义是git fetch 紧接着一个 git merge 命令,因为git fetch命令只会拉取数据,需要我们自己合并,如果有一个跟踪分支,git pull 会查找当前分支所跟踪的服务器与分支, 从服务器上抓取数据然后尝试合并入那个远程分支。建议显式使用fetch和merge更好。
变基
git rebase
当执行rebase操作时,git会从两个分支的共同祖先开始提取待变基分支上的修改,然后将待变基分支指向基分支的最新提交,最后将刚才提取的修改应用到基分支的最新提交的后面。
A
/
R
\
B
就是说,当你在分支B,执行 git rebase A时
- git将会先查出你基于AB的共同祖先R进行了哪些修改(比如在最后新增了一行)
- git将这些修改按顺序在A上执行(即在A的基础上,在最后新增一行)
R—— A —— C
当然,由于冲突可能发生,因此还需要切换回A,再次执行git merge B,处理冲突问题。
风险
如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。
还是使用上面是例子,当你已经把git rebase前的提交,放到了仓库中,而别人有可能基于B进行了一些修改,进行了提交,那么,就不要进行这次变基,因为它会让你们两个人的提交陷入混乱。
变基 与 合并
变基可以让我们的提交干净整洁,却也会失去一些历史数据
合并可以让我们保留所有过往的提交记录,但也会让提交显得一团糟。