git学习及分支管理策略

git分支使用的坏习惯

最近使用git提交代码发现大家的方式都不一样,自己在使用中也遇到了一些问题,导致代码危险。具体描述一下就是:
1.刚开始创建本地b_28分支与远程b_28对应。在此基础上,我自己改一个bug就基于这个又拉取了本地分支b_bug,一直在这个本地分支上修改,这个b_bug也一直没有关联任何远程代码。
2.后来远程b_featureA分支(原来是和b_28一样的)做了些版本小修改。
3.我不明就里的,本地又checkout了一个b_featureA,还把这些修改merge到了自己的b_bug。
4.管理员让我提交自己bug的修复。我将b_bug merge到本地b_28,然后先拉了origin b_28的更新,还好本地没冲突,然后push到了远端origin b_28。
5.远端分支的话,管理员b_featureA开发完了,要merge到b_28,并以后要在b_28基础上开发

其实这就有问题了,本来是用大家最新提交后的origin b_featureA去merge到origin b_28,但是由于我之前push到上面的代码包含了不必要的对origin b_featureA拉取,导致这个提交不安全。(事实上由于我在第3步之后又将b_bug中一个文件K恢复到了b_28版本,导致这个更新丢失了。这次远端merge的时候,K竟然还是未改的,b_featureA对它的改动并没有merge成功,但也没有提示,还好最后检查了。其实要是我没有恢复过这个K也就没事了)
因此,我犯了一个不必要的错误,要保证本地分支的parent只有一个,不要随便merge别的分支。
然后对于分支的使用原则,问了些人,大家习惯不一样,这几找了几个列子,想分清楚集中使用方法。


大家怎么用

主要关注功能分支:
我觉得可能不同的项目或者不同习惯的人需要不同的分支策略,这些没有必要非要按照某种规则去遵守。
一、阮一峰:Git分支管理策略 重点推荐,简单全面
1.创建一个功能分支:

git checkout -b feature-x develop

2.开发完成后,将功能分支合并到develop分支:

git checkout develop
git merge --no-ff feature-x

3.删除feature分支:

git branch -d feature-x

二、这个跟上面的是一样的方法,还有全面的命令,总结的很好:git使用规范
三、 这个稍微有点不一样:Git 问题, 一个 master, 多个新功能分支, 怎样有序地合并和提交?
git支持很多种工作流程,我们采用的一般是这样,远程创建一个主分支,本地每人创建功能分支,日常工作流程如下:
1.去自己的工作分支

$ git checkout work

2.工作
3.提交工作分支的修改

$ git commit -a

4.回到主分支

$ git checkout master

5.获取远程最新的修改,此时不会产生冲突

$ git pull

6.回到工作分支

$ git checkout work

7.用rebase合并主干的修改,如果有冲突在此时解决

$ git rebase master // 将改变当前工作分支的提交历史,rebase使得master上的更改在work上重演一遍

8.回到主分支

$ git checkout master

9.合并工作分支的修改,此时不会产生冲突。

$ git merge work

10.提交到远程主干

$ git push

这样做的好处是,远程主干上的历史永远是线性的。每个人在本地分支解决冲突,不会在主干上产生冲突。
注意衍合rebase的使用:分支的衍合
简单介绍rebase的:git rebase简介(基本篇)
Attention:一旦分支中的提交对象发布到公共仓库,就千万不要对该分支进行衍合操作。
如果你遵循这条金科玉律,就不会出差错。否则,人民群众会仇恨你,你的朋友和家人也会嘲笑你,唾弃你

四、一个小团队的使用:请推荐一个适合4-6人小团队的git代码管理模式?
整体项目分为master和develop两个分支,master主要用来发布网站使用.develop主要是用来分开使用.
1.平时每个人开发的时候,从develop中clone一下并创建一个开发者自己的分支,如zhang.(再有新加入者的时候,类似同样的方法分支另起一个名字li.).** Q:相当于每个开发者有一个自己的远程分支?按照人来确立分支而不是按照功能分支 **
2.当开发工作完成后,提交本地仓库并git push到自己的分支.
3.最后先将develop合并到自己的分支(开发期间可能被开发者进行过修改),以确保合并成功.
4.合并无误后,再将当前合并后的zhang分支合并到develop分支中.(注:这里的合并操作先是在本地分支合并.然后再合并到远程分支.有点多操作一步).
5.到最后一天工作结束后再将develop合并到master分支,通过master上线运行.
另外对于线上环境有紧急bug要修改的时候.再从master里创建一个分支.独立维护.结束后,再分别同步master和develop两个分支.

** 五、我打算用这个方式了,感觉跟第三个很类似:3.2 Git 分支 - 分支的新建与合并**
让我们来看一个简单的分支新建与分支合并的例子,实际工作中你可能会用到类似的工作流。 你将经历如下步骤:
1.开发某个网站。
2.为实现某个新的需求,创建一个分支。
3.在这个分支上开展工作。
正在此时,你突然接到一个电话说有个很严重的问题需要紧急修补。 你将按照如下方式来处理:
1.切换到你的线上分支(production branch)。
2.为这个紧急任务新建一个分支,并在其中修复它。
3.在测试通过之后,切换回线上分支,然后合并这个修补分支,最后将改动推送到线上分支。
4.切换回你最初工作的分支上,继续工作。

我认为的使用方式,还没有验证过不知道是不是好用:
比如有两个相互独立的任务featureA和featureB,简单点,他们都是从origin/dev拉过来开发。
第一种:

  1. 分别建立本地分支

$ git branch b_featureA origin/dev //新建本地分支featureA --关联远程分支dev
$ git branch b_featureB origin/dev //新建本地分支featureB --关联远程分支dev

  1. featureA和featureB在各自的分支上工作

  2. 最后修改完,先pull远端的代码,可能会有冲突,此时

$ git stash // 先暂存本地修改
$ git pull // 再拉取
$ git stash pop stash@{0} // 还原暂存区的内容,并解决冲突

  1. 解决冲突后

$ git push origin dev

  1. 如果本地分支featureA和本地分支featureB没用了,可以删除

这种方法没有一个比较稳定的本地分支。

第二种:
1.新建本地local_dev --关联远程dev

$ git branch local_dev origin/dev

2.基于本地的开发分支local_dev 创建两个功能分支,它们不关联任何远程分支

$ git branch b_featureA
$ git branch b_featureB

3.分别在featureA和featureB在各自的分支上工作

4.featureA开发完毕,切回到local_dev,它pull最新代码,此时不会有冲突。然后两种情况:
方法一:将最新的更改merge到local_dev,有可能冲突,也有rebase的,不熟悉先不用了。
没有冲突工作区也干净后,push到远端。删除本地featureA。
如果有暂时不想提的,可以stash起来,先不删除,然后进行后续开发。

方法二:再复杂一点,切回到featureA,将local_dev的更新merge过来,冲突在此处解决。
都提交后,切回到local_dev,将featureA的更新merge过来,此时不会再有冲突。
local_dev推送到远端。

方法三:我没想到,一个同事说的,切回到featureA,将origin/dev的更新merge过来,就是直接将远端分支的更改merge过来,有冲突就在此处解决。然后都开发完毕后,切回到local_dev,将featureA的更新merge过来,然后将local_dev推送到远端。比方法二少一步merge,然后好像也没什么大的缺点。
不过还没用过直接将远程分支merge到本地这种未对应远程分支的分支上。而且,经常看到这样的忠告:

不要用git pull,用git fetch和git merge代替它。

5.featureB同上

我之前是用的最复杂的第二种的方法二。好处是冲突都是在本地最末端的分支上,和其他功能都不会相互影响,就是操作太麻烦了。
打算采用上面的三,期待有更好的方法。


一些常用命令

基本命令

$ git remote add origin git@github.com:michaelliao/learngit.git // 将本地的git目录和远程建好的git目录关联
$ git add . // 添加所有文件到git版本控制,注意不是git stash
$ git commit -m "commit log" // 提交修改,必须要加注释
$ git checkout -b story remotes/origin/story // 在本地创建story分支并track,可以pull和push
//恢复版本
$ git checkout -- readme.txt // 把readme.txt文件在工作区的修改全部撤销,还未添加到暂存区
$ git reset HEAD readme.txt // 已经add,还没有commit,先用这句unstage,在用上一句
// 如果已经commit
$ git log // 查看提交记录,确定恢复到哪个版本
$ git log -p // 查看详细提交记录
$ git reset --hard HEAD^ // 恢复到上一个版本,因为HEAD指的是当期版本,HEAD是上一个,HEAD^是上上个,其余的可以用版本编号的前几位来恢复
$ git reset --hard 3628164 // 前几位来恢复,只要这个号码能唯一确定一个版本就可以
$ git push -u origin b_28 // 将本地修改的b_28推送到远端b_28,加上了-u参数,Git不但会把本地的分支内容推送的远程新的分支,还会把本地的分支和远程的分支关联起来,在以后的推送或者拉取时就可以简化命令。第一次推送分支的所有内容,以后就可以用git push origin b_28了
$ git branch -d feature // 删除feature分支
$ git branch -a // 加上-a参数可以查看远程分支,远程分支会用红色表示出来
$ git branch -vv // git branch -vv(两个v),就能够看到本地分支跟踪的远程分支。
$ git merge --no-ff develop // 默认情况下,Git执行"快进式合并"(fast-farward merge)加上这个参数就是非快进式合并
$ git push origin :branch_you_want_to_delete // 删除远程的某个分支,注意冒号前面有个空格,慎用

跟踪远程分支
从远程分支 checkout 出来的本地分支,称为 跟踪分支 (tracking branch)。跟踪分支是一种和某个远程分支有直接联系的本地分支。在跟踪分支里输入 git push,Git 会自行推断应该向哪个服务器的哪个分支推送数据。同样,在这些分支里运行 git pull 会获取所有远程索引,并把它们的数据都合并到本地分支中来。
在克隆仓库时,Git 通常会自动创建一个名为 master 的分支来跟踪 origin/master。这正是 git push
和 git pull 一开始就能正常工作的原因。当然,你可以随心所欲地设定为其它跟踪分支,比如 origin
上除了 master 之外的其它分支。刚才我们已经看到了这样的一个例子:git checkout -b [分支名] [远程名]/[分支名]。如果你有 1.6.2 以上版本的 Git,还可以用 --track
选项简化:
$ git checkout --track origin/serverfixBranch //serverfix set up to track remote branch serverfix from origin.Switched to a new branch 'serverfix'

要为本地分支设定不同于远程分支的名字,只需在第一个版本的命令里换个名字:
$ git checkout -b sf origin/serverfixBranch //sf set up to track remote branch serverfix from origin.Switched to a new branch 'sf'

git本地新建一个分支后,如果没有做远程分支关联, git 会在git pull, git push操作中提示你显示的添加关联。你只要没有显示指定,git pull的时候就提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建。如果新建分支的时候没有指定,随后再指定本地dev分支与远程origin/dev分支的链接,可以用下面的命令

$ git branch --set-upstream dev origin/dev

工作区域暂存

$git stash
$ git stash list
$ git stash apply
$ git stash drop stash@{0}
$ git stash pop //来重新应用储藏,同时立刻将其从堆栈中移走。


学习参考资料:看了这些就够了

1.Git常用操作和技巧
2.git - 简明指南
3.Pro Git简体中文版
4.廖雪峰 简明git教程
5.Git Commands and Best Practices Cheat Sheet

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 1. 安装 Github 查看是否安装git: $ git config --global user.name "...
    Albert_Sun阅读 13,626评论 9 163
  • 如果有一天 你走进我的心里 你会哭,因为里面全是你 如果有一天 我走进你的心里 我也会哭 因为那里没有我 不知道 ...
    光落在你脸上阅读 359评论 3 2