Feature分支:

通常添加一个新功能,我们可定不希望因为一些实验性的代码而把分支搞乱,所以每添加一个功能最好是建一个feature分支,在feature分支上面开发、实验,完成后根据需要进行合并,最后删除该featrue分支。

下面,举例一个场景:
在工作中,当我们接到一个新的功能,该功能计划于下一个开发版本中。开始准备开发。

1、创建分支
$git checkout -b feature-car
2、快速的开发完毕,提交代码
$git add NewCarController.java

$git commit -m '新车辆档案'

3、切回dev,合并到dev分支上
$git checkout dev
在这里的合并和其他分支的合并、删除是一样的。
就在合并的此时,接到了上级的命令,因为合同问题,该功能被砍掉不需要了。这个分支也包含了一些比较重要的代码,既然不需要了还是需要就地销毁的
4、删除feature分支
$git branch -d feature-car
error: The branch 'feature-car' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature-car'.
咦?提示删除失败报错了?还好Git友情提示,feature-car分支还没有被合并,如果删除将丢失掉该分支的所有修改,如果要强行删除,需要使用大写的-D参数。
好了,现在我们强行删除
$git branch -D featrue-car
总结:
开发一个新的功能,最好是新建一个分支,如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。

多人协作:

从远处仓库克隆时,实际上git自动将本地的master分支与远程的master分支对应起来了,并且远程仓库的默认名是origin。
查看远程仓库信息使用git remote 或 用查看信息更详细的 git remote -v

$ git remote 
GitGo

$ git remote -v
GitGo   git@git.oschina.net:Mr.bai/GitGo.git (fetch)
GitGo   git@git.oschina.net:Mr.bai/GitGo.git (push)

上面显示的抓取和推送的地址,没有推送权限的就看不到push地址。

推送分支
把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上
$ git push GitGo master
如果要推送其他分支
$ git push GitGo dev
当然,也并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?
master分支是主分支,因此要时刻与远程同步;
dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
总之,就是在Git中,分支完全可以在本地自己藏着玩,是否推送,根据你的需要而定。

 

抓取分支
在多人协作开发时,大家都会往master和dev分支上推送各自的修改。
当我们从远程库克隆一个项目,默认情况下只能看到本地的master。可以使用git bransh查看。
然后现在你的小伙伴需要在dev分支上开发,就必须创建远程的origin和dev分支到本地,于是他用git checkout -b dev origin/dev 命令创建本地dev分支,他就可以在dev上继续修改,然后时不时的把dev分支push到远程。
$ git add test.txt
$ git commit -m 'add Test.txt'
$ git push origin dev
你的小伙伴向origin/dev分支推送了他的提交,而碰巧你也对同样的文件做了修改,并试图推送
$ git add test.txt
$ git commit -m 'add test.txt'
$ git push origin dev
Togithub.com:KerryPak/learngit.git
! [rejected] dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@github.com:KerryPak/learngit.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送
$ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

git branch --set-upstream-to=origin/<branch> dev

git pull也失败了,原因是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接
$ git branch --set-upstream-to=origin/dev dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.

再pull
$ git pull
Auto-merging test.txt
CONFLICT (add/add): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.

这回git pull成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,提交,再push
$ git commit -m "fix test conflict"
[dev 57c53ab] fix test conflict

$ git push origin dev
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 621 bytes | 621.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
   7a5e5dd..57c53ab  dev -> dev

因此,多人协作的工作模式通常是这样:
1、首先,可以试图用git push origin <branch-name>推送自己的修改;
2、如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
3、如果合并有冲突,则解决冲突,并在本地提交;
4、没有冲突或者解决掉冲突后,再用git push origin <branch-name>推送就能成功!
如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。
小结:
1、查看远程库信息,使用git remote -v;
2、本地新建的分支如果不推送到远程,对其他人就是不可见的;
3、从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
4、在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
5、建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name;
6、从远程抓取分支,使用git pull,如果有冲突,要先处理冲突

Rebase

在版本库中,经过我们一次次的合并push之后,分子就变成了下面这个样子
$ git log --graph --pretty=oneline --abbrev-commit
* d1be385 (HEAD -> master, origin/master) init hello
* e5e69f1 Merge branch 'dev'
|\
| * 57c53ab (origin/dev, dev) fix env conflict
| |\
| | * 7a5e5dd add env
| * | 7bd91f1 add new env
| |/
* | 12a631b merged bug fix 101
|\ \
| * | 4c805e2 fix bug 101
|/ /
* | e1e9c68 merge with no-ff
|\ \
| |/
| * f52c633 add merge
|/
* cf810e4 conflict fixed

对于有强迫症的人来说可能会看起来很乱。
Git有一种称为rebase的操作,有人把它翻译成“变基”,将分支中的所有提交(commit)合并都调整合并(应用)在分支的基线上。 想让分支历史看起来像没有经过任何合并一样,你也许可以用 git rebase
$ git checkout dev
$ git rebase origin
这些命令会把你的"dev"分支里的每个提交(commit)取消掉,并且把它们临时 保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后把"mywork"分支更新 为最新的"origin"分支,最后把保存的这些补丁应用到"dev"分支上。
《rebase 前》
《rebase 中》
当'dev'分支更新之后,它会指向这些新创建的提交(commit),而那些老的提交会被丢弃。 如果运行垃圾收集命令(pruning garbage collection), 这些被丢弃的提交就会删除. (请查看 git gc)
《rebase 后》
好了,我们现在再次查看一下git log
$ git log --graph --pretty=oneline --abbrev-commit
* 7e61ed4 (HEAD -> master) add author
* 3611cfe add comment
* f005ed4 (origin/master) set exit=1
* d1be385 init hello
...

 

这就是rebase操作的特点:把分叉的提交历史“整理”成一条直线,看上去更直观。缺点是本地的分叉提交已经被修改过了。
最后,通过push操作把本地分支推送到远程
$ git push origin master
远程分支的提交历史现在也是一条直线啦。
在rebase的过程中,也许会出现冲突(conflict). 在这种情况,Git会停止rebase并会让你去解决 冲突;在解决完冲突后,用"git-add"命令去更新这些内容的索引(index), 然后,你无需执行 git-commit,只要执行:
$ git rebase --continue
这样git会继续应用(apply)余下的补丁。
在任何时候,你可以用--abort参数来终止rebase的行动,并且"mywork" 分支会回到rebase开始前的状态。
$ git rebase --abort
小结:
1、rebase操作可以把本地未push的分叉提交历史整理成直线;
2、rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。

 

标签: Git, Feature分支, Git多人协作, Git Rebase, Git抓取分支, Git推送分支

添加新评论