分支
查看分支
显示所有的分支:
git branch
查看当前所在的分支及提交记录:
git-show-branch
新建分支
想要建一个新的叫experimenal
的分支:
git branch experimenal
把新建的分支添加到远程
git push --set-upstream origin experimenal git push
切换分支
在切换分支之前要保证当前分支处于commit
状态。
切换到experimenal
分支:
git checkout experimenal
使用checkout
可以在多个分支上随意切换。在一个分支上的操作不会影响到另一个分支。
可以把分支的创建与切换合并为一步:
git checkout -b experimenal
合并分支
两个分支必须都已经commit
才能合并。
要把experimenal
合并到master
,要先切到master
:
git checkout master
然后把experimenal
合并过来:
git merge experimenal
如果有冲突,会把冲突中的文件修改为diff格式的状态。要手动修正了以后再提交:
git commit -a
可以通过图型界面查看分支过程:
gitk
合并成功了以后可以删除原来的experimenal
:
git branch -d experimenal
如果分支还没有合并,可以用大写-D
表示强制删除,通常在分支失败时用:
git branch -D experimenal
撤消合并分支
git 到底是个多么奇葩的管理工具,一个问题能有这么多解释,一眼还不出来那个是对的。 http://git-scm.com/blog/2010/03/02/undoing-merges.html 这是官方的解答,待我看完,在此翻译一下。
======================简单翻译开始====================
由于太多人问怎么撤销 merge 了,于是 git 官方出了这份教程,表示在 git 现有的思想体系下怎么达到撤销 merge 的目标。
方法一,reset 到 merge 前的版本,然后再重做接下来的操作,要求每个合作者都晓得怎么将本地的 HEAD 都回滚回去:
$ git checkout 【行merge操作时所在的分支】 $ git reset --hard 【merge前的版本号】
方法二,当 merge 以后还有别的操作和改动时,git 正好也有办法能撤销 merge,用 git revert:
$ git revert -m 【要撤销的那条merge线的编号,从1开始计算(怎么看哪条线是几啊?)】 【merge前的版本号】 Finished one revert. [master 88edd6d] Revert "Merge branch 'jk/post-checkout'" 1 files changed, 0 insertions(+), 2 deletions(-)
这样会创建新的 commit 来抵消对应的 merge 操作,而且以后 git merge 【那个编号所代表的分支】 会提示:
Already up-to-date.
因为使用方法二会让 git 误以为这个分支的东西都是咱们不想要的。
方法三,怎么撤销方法二:
$ git revert 【方法二撤销merge时提交的commit的版本号,这里是88edd6d】 Finished one revert. [master 268e243] Revert "Revert "Merge branch 'jk/post-checkout'"" 1 files changed, 2 insertions(+), 0 deletions(-)
这样就行了,可以正常 merge 了,不过可能会有很多冲突噢!!
$ git merge jk/post-checkout Auto-merging test.txt Merge made by recursive. test.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
=====================简单翻译结束====================
最后的最后,还是觉得顶上那些都麻烦爆了。前端天天用 WebStorm 写代码的看过来: WebStorm 右键点击项目文件或文件夹,有一个:
Local History -> Show History
点开后出现一个窗口,可以看到所有的本地改动。找到合适的那份,按左上角那个:
Revert
按钮,也就是个紫色的弯曲的小箭头就回去了。在文件量不大的时候十分管用,强烈推荐。
删除分支
# 删除本地分支 git branch -d localBranchName # 删除远程分支 git push origin --delete remoteBranchName
长期分支
长期分支建议开rerere
,git config rerere.enable true
详情man git-rerere
推荐分支规划
以master
为基础建立release
分支作为打包发布的内容:
git checkout -b release master
以master
为基础建立develop
分支作为开发版本:
git checkout -b develop master git push -u origin develop
每个任务再从develop
里再分出分支来:
git checkout -b feature01 develop
如果生产环境上的bug,那再从master
分出hotfix
分支来:
git checkout -b hotfix master
开发工作流程
开发前
新建临时分支
新任务从develop
里分出分支来:
git checkout develop git pull git checkout -b feature01 develop
修改软件版本号
版本号改为1.0.0-feature01-SNAPSHOT
。
vim pom.xml # update version vim README.md # update readme file add TODO info git commit -a -m 'bla bla bal'
加上TAG
打上tag中的「feature」部分:
git tag -a 'v1.0.0-feature01-SNAPSHOT' -m 'Version 1.0.0-feature-add-modole' git push origin --tags
开发完成后
从develop
分支合并过来
开发完以后把最新版本的develop
合并过来,因为可以有其他的任务已经提交了:
git checkout develop git pull git checkout feature01 git merge --no-ff develop
加上TAG
打上tag后缀-M
表示已经合并过develop
分支的内容:
git tag -a 'v1.0.0-feature01-SNAPSHOT-M' -m 'Version 1.0.0-feature-add-modole merged' git push origin --tags
修改版本号:开发版本
增加版本号,去掉「feature」,改为1.0.1-SNAPSHOT
。
vim README.md # update readme file add change log vim pom.xml # update version git commit -a -m 'bla bla bal'
提交到develop
git checkout develop git merge --no-ff feature01 # 注释要写明增加了那些feature
打上标签-M-feature01-
:
git tag -a 'v1.0.1-M-feature01-SNAPSHOT' -m 'Version 1.0.1-M-feature01-SNAPSHOT' git push origin --tags
发布版本
-
检查
pom.xml
:- 检查所有依赖,把快照版本变为正式版本。
-
检查文档
README.md
:- TODOList已经完成。
把主干上别人提交的内容合并到当前分支中(比如可能有:hotfix之类的分支有更新内容) :
git checkout master git pull git checkout develop git merge --no-ff master git tag -a 'v${version.from}-SNAPSHOT-M' -m 'Version v${version.from}-SNAPSHOT merged'
版本号升级合并到主干
-
pom.xml
去掉SNAPSHOT
,项目的版本号由快照版变为正式版。
git commit -a -m 'v${version.from}-SNAPSHOT-M' git checkout master git merge --no-ff develop # comment : detail of new features git tag -a 'v${version.from}' -m 'Version ${version.from}' git push && git push origin --tags git checkout develop git merge --no-ff master
-
检查
pom.xml
:- 提升版本号为下一版本的快照。
-
检查文档
README.md
:- 为新的版本号增加TODOList。
git commit -a -m 'v${version.to}-SNAPSHOT' git tag -a 'v${version.to}-SNAPSHOT' -m 'Version ${version.to}-SNAPSHOT' git push && git push origin --tags
布署到生产环境
提交到release
分支:
git checkout release git merge master
修改配置文件,参数改为生产环境参数。
修改版本号,加上release
,改为1.0.1-RELEASE
git commit
打上标签:
git tag -a 'v1.0.1-RELEASE' -m 'Version 1.0.1 release' git push origin --tags
其他
冲突处理
合作开发与合并分支都有可能发生冲突,看到如下错误信息:
Automatic merge failed; fix conflicts and then commit the result.
这个时候要手动排除冲突,源代码被会git修改。以====
分隔冲突的两边。修改完成了
以后可以再次提交:
git commit -a
有一点要注意,git会自动在merge完成以后添加一个原始冲突的备份.orig
文件。如果嫌
这个文件碍眼的话可以设置不生成这个东西:
用命令:
git config --global mergetool.keepBackup false
或直接改配置:
[mergetool] keepBackup = false
使用vimdiff
设置合并工具为vimdiff,修改~/.gitconfig
:
[diff] tool = vimdiff [merge] tool = vimdiff [difftool] prompt = false
以后merge会调用vimdiff:
git mergetool
在vimdiff窗口中会上面一半会分别显示本地版本、原始版本、过程版本,下半部分是冲突 的版本:
窗口切换:CONTROL+w w
跳到上一个、下一个冲突点:[c
、]c
取得某窗口中的内容::diffget window
放置内容到某窗口::diffput window
diffget
和diffput
都要指定窗口,怎么指定窗口呢?有两个方法:
一个方法是用:buffers
查出来Buffer编号。一般来说下半编号是1,上面三个是从2到4。
另一个方法是用关键字匹配。vimdiff一般把上面三个窗口中的文件名为XXXX.REMOTE.yyy
,XXXX.BASE.yyy
,XXXX.LOCAL.yyy
。用diffget REMOTE
就是取远程的。
经过合并以后的版面会有点乱,可以用:diffupdate
重新生成diff
格式。
保存当前窗口用w
,关闭全部窗口用a
。
使用meld
(略)
场景模拟:合作开发
假设现在有另一个人(用户B)和我合作。他的工作目录在:
mkdir wubi2
从仓库复制源代码到本地
用户B从我的版本库中导出。
在没有服务器的情况下:
git clone wubi wubi2
通过服务器:
git clone git://git.jade.com/wubi wubi2
然后别人可以在我的代码基础上进行开发,然后提交:
git commit -a
发布本地提交的内容
用户B提交的内容只有自己能看到,他想让别人得到他的工作成果的话,就要把他提交的 内容发布给其他开发者。
如果服务器允许直接发布,那可以直接发布到服务器:
git push
有些项目(如:linux kernel)不允许提交到版本库,只能做成补丁文件发邮件给别人:
git format-patch origin
取得其他人提交的内容
回到我这边,我知道别人已经提交了,现在要取得别人的工作成果。如果不放心别人的工作
,根据别人的远程仓库名为master
的分支在本地建立一个名为otherone
的分支。
在没有服务器的情况下:
cd wubi git fetch ../wubi2 master:otherone
有服务器的情况下(区别就是源地址,以后不再说明没有服务器的情况了):
cd wubi git fetch git://git.jade.com/wubi master:otherone
比较一下别人改了哪些地方
git whatchanged -p master..otherone
如果认为对方改错了,可以删除掉对方的修改
git branch -D otherone
如果觉得没有问题了可以用pull
命令导入别人的修改。其实pull
命令相当于是fetch
命令和merge
命令的一个组合。当然如果信任对方的话,也可以不建立分支检查(略过
上面的所有步骤)直接导入。
从目录:
git pull ../wubi2 master
从服务器:
git pull git://git.jade.com/wubi master
从服务器也可以不加参数,直接:
git pull
其实,用git pull .
就相当于git merge
。
用户B继续开发时先要取得我的工作成果,可以直接pull
不用加参数。因为clone
的时候
已经记住了来源:
git pull