2019-04-22 Git本地分支(Branch)的用途和用法

一. 分支 (branch) 

用于:

            1. 由于debug或增加功能,从原有程序项目分出新项目。最终可以合并回原项目

                分支常命名为:

                    bug/<bug_id>/<bug_说明>

                    feat/<新功能_说明>

            2. 原项目(master)为release-to-user 分支,另分出一个项目,做develope。最终合并(提交)回原项目

                    分支常命名为:develop

                    这种用途,合并时由于master分支始终无人修改,会采用fast-forward合并模式 (master上将没有新commit节点产生)。所以,为了产生新commit节点,须: git merge --no-ff  develop

工作原理:

            创建新分支时,从当前分支的指定的commit节点,作以下动作:

                1. 复制track list 

                2. 记录这个commit节点为新分支的HEAD (用于下次切换)

            切换分支时,包扩了以下动作

                1. 找到要切换分支的指定的commit节点 (默认是该分支的HEAD)

                2. 比较这个commit节点的数据内容 和当前分支的在文档库里的对应版本,找出不同的文件

                3. 取回在这些不同的文件到working directory

                4. 覆盖 staging area数据

                5. 替换 track list

                6. 根据5删除working directory中不在track list上的文件

        可见:   各分支,共享 repository+staging area+working directory+.gitignore;但各分支有自己的track list,且在分支生成后,各不相干。

管理命令:

    A. git branch  <新分支名字>   [<起源分支>] [<起源的commit节点标识符或标签>]          创建新分支,但不切换

            起源分支:默认是当前分支

            起源commit节点:默认是起源分支的HEAD

    B. git branch                                        察看文档库中所有分支

        * gitk --all 能在GUI里显示出所有分支的演进图。如果不加-all参数,只显示当前分支的

        * git log --graph --oneline --all --decorate  效果同上

    C. git branch -d <待删分支名字>        删除分支。不能删除当前分支。只能删除已合并完的分支

            支持参数:

                1. -D    强制删除那个分支,放弃它的修改,不等合并

    D. git checkout  <分支名字>               切换分支。只有当前分支的修改已提交版本库,才有效

            支持参数:

                1. -b : 创建并切换到新分支

                2. -f : 不判断当前分支修改是否已提交版本库,强制checkout的6个动作 (导致当前分支的修改丢失)

        * 执行checkout之前,一定要做git status, 确保 :没提交的提交;当前分支的修改,不要误带入要切入的分支

        * 正常的2种checkout的使用情况: 

                    git checkout <分支>  -->分支切换操作

                    git checout  <commit节点>  <文件名> -->取回当前分支某文件的历史版本  

            不正常的使用情况: 

                    git checkout  <commit节点>  -->  这时 HEAD指向此commit节点形成detach head状态;当git add和git commit后,长出无名分支。

                    修复:

                        方法A:  删除此无名分支。 步骤:1. 命名当前分支 (git branch -m xxx),在这之前不要切换出去  2. 切换出去并删除此分支 (git checkout master; git branch -D xxx)

                        方法B: 合并无名分支到master上。步骤:1. 命名当前分支 (git branch -m xxx),在这之前不要切换出去  2. 切换出去,合并此分支 (git checkout master; git merge xxx)

    E. git branch -m <新分支名字>            给当前分支改名字

    F. git merge <分支名字B>                   合并另一分支到当前分支,没冲突的情况下,动作包含了git add -A .和 git commit的动作 。

            被合并分支B不会被删除,也不会有任何变化。当前分支A,会有新的HEAD, 他的父节点,HEAD^1是A自身的HEAD^, HEAD^2是B的HEAD。

           因此,合并完成后,如果要撤销这个合并:不需要对分支B做任何操作;对分支A,消磁退到它的父节点:

                git reset --hard HEAD^

            合并没完成(由于冲突),撤销这个合并:

                git merge --abort

            * 相对分支生长点(叫base节点)的版本,没有修改发生的分支,无法作为被合并的分支角色。

            * 两种合并机制:

                1.  fast-forward      即当前分支没有过修改。合并时,HEAD快进到被合并分支的HEAD。只有一个HEAD^

                     选项支持: --no-ff        放弃ff模式,为当前分支另生成HEAD,等效于3-way。

                2.  3-way                即两个分支都发生过修改。合并室,生成新HEAD。3-way有两个HEAD^                    

    G.  git rebase  <源分支>                         把当前分支的base节点,推进到源分支的新HEAD节点。没冲突的情况下,动作包含了git add -A .和 git commit的动作 。

           情景:

                当前分支开发了太久,master分支都更新了。如果用git merge,会形成网状演进图,不清晰。所以使用rebase。

                不是和此分支是团队共享的分支。

           支持选项:

                1.  git rebase --skip         跳过某冲突文件

                2.  git rebase --abort       放弃未完成的演进

                3.  git rebase --continue    fix冲突(同二)以后,手工git add ., 然后提交 

二、冲突

原因: 

    3-way merge时,两个分支间存在修改同一个文件的情况

情景:

    merge -- 两分支合并

    rebase -- 源分支的新HEAD节点版本的更新运用到当前分支中,即当前分支base节点向前推进到源分支的新的HEAD

    cherry-pick -- 指定commit节点 合并到working directory

    revert -- 指定commit节点的前一节点版本 合并到working directory, 即让working directory的修改基于的base,向历史回退。是cherry-pick的原理一样,看上去和git reset --hard 一样,但reset不会创建新的commit节点,revert更不会删任何commit节点。


解决办法1  手工fix:

    以上情景 探测到冲突时,会在冲突文件中加入<<<<<<<标识冲突开始,>>>>>>标识冲突结束。因此: 

        step 1. vi 这个冲突文件,fix共同修改的部分,删掉标识符。

        step 2. git diff             对比确认

        step 3. git add .          手工更新staging area

        step 4. git commit -m “操作说明”    手工提交

解决办法2 mergetool:    

    前提条件:git配置mergetool --

        git config --global  merge.tool kdiff3

        git config --global merge.tool.kdiff3.path  “<安装路径>“ 

    然后,git merge因为冲突失败后:

        step 1. git mergetool            --> kdiff3会自动作好上面方法1的step1,2

        step 2. 人review kdiff的劳动成果,保存退出。mergetool会自动作上面方法1的step3.

        step 3. git commit -m “操作说明”    手工提交

三、让合并来服务本地文件

    这些动作,都会产生新的commit节点

    操作命令:

        A.  git cherry-pick <commit节点的标识符或标签>        合并commit节点版本到本地的文件。没冲突的情况下,动作包含了git add -A .和 git commit的动作 。

            支持选项::

                1.  git cherry-pick --abort            合并没完成(由于冲突),撤销这个合并

                2. git cherry-pick --continue        合并冲突fix以后,手工做这个动作,等效于merge的冲突解决后的git commit。

            冲突解决:

                同merge,只是最后的手工git commit,被git cherry-pick --continue  替换。

        B. git revert <commit节点的标识符或标签>                    合并commit节点版本的前一个版本到本地的文件,动作包含了git add -A .和 git commit的动作 。

            支持选项:

                1.  git revert  --abort                    合并没完成(由于冲突),撤销这个合并

            冲突解决:

                同merge

四、如何反悔

对于merge、rebase (也可以是revert、cherry-pick)后,后悔想恢复版本库到操作之前。git reset --hard <commit节点标识符或标签>支持。

但关键是找到操作之前的那个commit节点标识符。这里,需要reflog

    操作命令:

        git reflog <HEAD或分支名称>                列出该分支的所有的commi节点和对它对应的操作, 靠上的是新的

        git reset --hard <commit节点标识符或标签>

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

推荐阅读更多精彩内容