Jade Dungeon

分支

查看分支

显示所有的分支:

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

长期分支

长期分支建议开rereregit 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

diffgetdiffput都要指定窗口,怎么指定窗口呢?有两个方法:

一个方法是用:buffers查出来Buffer编号。一般来说下半编号是1,上面三个是从2到4。

另一个方法是用关键字匹配。vimdiff一般把上面三个窗口中的文件名为XXXX.REMOTE.yyyXXXX.BASE.yyyXXXX.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