zoukankan      html  css  js  c++  java
  • 第二篇:版本控制git之分支

    有人把 Git 的分支模型称为它的`‘必杀技特性’',也正因为这一特性,使得 Git 从众多版本控制系统中脱颖而出。 为何 Git 的分支模型如此出众呢? Git 处理分支的方式可谓是难以置信的轻量,创建新分支这一操作几乎能在瞬间完成,并且在不同分支之间的切换操作也是一样便捷。 与许多其它版本控制系统不同,Git 鼓励在工作流程中频繁地使用分支与合并,哪怕一天之内进行许多次。 理解和精通这一特性,你便会意识到 Git 是如此的强大而又独特,并且从此真正改变你的开发方式。

    分支操作

    1、git branch    查看所有分支

    2、git branch name   创建分支

    Git 是怎么创建新分支的呢? 很简单,它只是为你创建了一个可以移动的新的指针。 比如,创建一个 testing 分支, 你需要使用 git branch 命令:

    $ git branch testing

    3、git checkout name    切换分支

    要切换到一个已存在的分支,你需要使用 git checkout 命令。 我们现在切换到新创建的 testing 分支去:

    $ git checkout testing

    创建一个新的分支,并切换到刚创建的这个分支中,一条命令搞定:

    $ git checkout -b dev
    Switched to a new branch 'dev'

    git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:

    $ git branch dev
    $ git checkout dev
    Switched to branch 'dev'

    然后,用git branch命令查看当前分支:

    $ git branch
    * dev
      master

    git branch命令会列出所有分支,当前分支前面会标一个*号。

    4、git branch -d name   分支删除

    5、git merge name  分支合并

    假设你正在通过一个临时新分支bug-53修复一个bug,修复后需要需要与master分支进行合并。

    $ git checkout master
    Switched to branch 'master'
    $ git merge bug-53
    Merge made by the 'recursive' strategy.
    index.html |    1 +
    1 file changed, 1 insertion(+)

    遇到冲突时的分支合并

    有时候合并操作不会如此顺利。 如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。 如果你对 #53 问题的修改和有关 hotfix 的修改都涉及到同一个文件的同一处,在合并它们的时候就会产生合并冲突:

    $ git merge iss53
    Auto-merging index.html
    CONFLICT (content): Merge conflict in index.html
    Automatic merge failed; fix conflicts and then commit the result.

    此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。 你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件:

    $ git status
    On branch master
    You have unmerged paths.
      (fix conflicts and run "git commit")
    
    Unmerged paths:
      (use "git add <file>..." to mark resolution)
    
        both modified:      index.html
    
    no changes added to commit (use "git add" and/or "git commit -a")

    任何因包含合并冲突而有待解决的文件,都会以未合并状态标识出来。 Git 会在有冲突的文件中加入标准的冲突解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突。 出现冲突的文件会包含一些特殊区段,看起来像下面这个样子:

    <<<<<<< HEAD:index.html
    <div id="footer">contact : email.support@github.com</div>
    =======
    <div id="footer">
     please contact us at support@github.com
    </div>
    >>>>>>> iss53:index.html

    这表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在 ======= 的下半部分。 为了解决冲突,你必须选择使用由 ======= 分割的两部分中的一个,或者你也可以自行合并这些内容。 例如,你可以通过把这段内容换成下面的样子来解决冲突:

    <div id="footer">
    please contact us at email.support@github.com
    </div>

    上述的冲突解决方案仅保留了其中一个分支的修改,并且 &lt;&lt;&lt;&lt;&lt;&lt;&lt; , ======= , 和 &gt;&gt;&gt;&gt;&gt;&gt;&gt; 这些行被完全删除了。 在你解决了所有文件里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。

    分支管理

    面试题:

    你们公司如何基于git做版本控制
    
    master 分支是用来存放生产环境的代码
    
    dev分支是用来开发的
    
    会临时创建bug分支来修复线上的bug,修复完成合并到master,删除bug分支

    bug分支

    软件开发中,bug就像家常便饭一样。有了bug就需要修复,在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。

    当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101来修复它,但是,等等,当前正在dev上进行的工作还没有提交:

    $ git status
    On branch dev
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
        new file:   hello.py
    
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git checkout -- <file>..." to discard changes in working directory)
    
        modified:   readme.txt

    并不是你不想提交,而是工作只进行到一半,还没法提交,预计完成还需1天时间。但是,必须在两个小时内修复该bug,怎么办?

    幸好,Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:

    $ git stash
    Saved working directory and index state WIP on dev: f52c633 add merge

    现在,用git status查看工作区,就是干净的(除非有没有被Git管理的文件),因此可以放心地创建分支来修复bug。

    首先确定要在哪个分支上修复bug,假定需要在master分支上修复,就从master创建临时分支:

    $ git checkout master
    Switched to branch 'master'
    Your branch is ahead of 'origin/master' by 6 commits.
      (use "git push" to publish your local commits)
    
    $ git checkout -b issue-101
    Switched to a new branch 'issue-101'

    现在修复bug,需要把“Git is free software ...”改为“Git is a free software ...”,然后提交:

    $ git add readme.txt 
    $ git commit -m "fix bug 101"
    [issue-101 4c805e2] fix bug 101
     1 file changed, 1 insertion(+), 1 deletion(-)

    修复完成后,切换到master分支,并完成合并,最后删除issue-101分支:

    $ git checkout master
    Switched to branch 'master'
    Your branch is ahead of 'origin/master' by 6 commits.
      (use "git push" to publish your local commits)
    
    $ git merge --no-ff -m "merged bug fix 101" issue-101
    Merge made by the 'recursive' strategy.
     readme.txt | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)

    太棒了,原计划两个小时的bug修复只花了5分钟!现在,是时候接着回到dev分支干活了!

    $ git checkout dev
    Switched to branch 'dev'
    
    $ git status
    On branch dev
    nothing to commit, working tree clean

    工作区是干净的,刚才的工作现场存到哪去了?用git stash list命令看看:

    $ git stash list
    stash@{0}: WIP on dev: f52c633 add merge

    工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:

    一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;

    另一种方式是用git stash pop,恢复的同时把stash内容也删了:

    $ git stash pop
    On branch dev
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
        new file:   hello.py
    
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git checkout -- <file>..." to discard changes in working directory)
    
        modified:   readme.txt
    
    Dropped refs/stash@{0} (5d677e2ee266f39ea296182fb2354265b91b3b2a)

    你可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:

    $ git stash apply stash@{0}

    dev分支

    软件开发中,总有无穷无尽的新的功能要不断添加进来。

    添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个dev分支,在上面开发,完成后,合并,最后,删除该dev分支。

    现在,你终于接到了一个新任务:开发代号为Vulcan的新功能,该功能计划用于下一代星际飞船。

    于是准备开发:

    $ git checkout -b dev-vulcan
    Switched to a new branch 'dev-vulcan'

    5分钟后,开发完毕:

    $ git add vulcan.py
    
    $ git status
    On branch dev-vulcan
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
        new file:   vulcan.py
    
    $ git commit -m "add feature vulcan"
    [feature-vulcan 287773e] add feature vulcan
     1 file changed, 2 insertions(+)
     create mode 100644 vulcan.py
    
    

    切回dev,准备合并:

    $ git checkout dev

    一切顺利的话,feature分支和bug分支是类似的,合并,然后删除。

    但是!

    就在此时,接到上级命令,因经费不足,新功能必须取消!

    虽然白干了,但是这个包含机密资料的分支还是必须就地销毁:

    $ git branch -d  dev-vulcan
    error: The branch 'dev-vulcan' is not fully merged.
    If you are sure you want to delete it, run 'git branch -D dev-vulcan'.

    销毁失败。Git友情提醒,dev-vulcan分支还没有被合并,如果删除,将丢失掉修改,如果要强行删除,需要使用大写的-D参数。。

    现在我们强行删除:

    $ git branch -D dev-vulcan
    Deleted branch dev-vulcan (was 287773e).

    终于删除成功!

     

    #stash  相关指令
    
    git stash  将当前开发的内容放在"某个地方"
    
    git stash pop 恢复当前的工作目录,并删除
    
    git stash list  查看stash列表
    
    git stash drop 删除stash
    
    git stash apply 恢复当前的工作目录,不删除stash
  • 相关阅读:
    洛咕 P2403 [SDOI2010]所驼门王的宝藏
    洛咕 P2480 [SDOI2010]古代猪文
    洛咕 P2447 [SDOI2010]外星千足虫
    CF618F Double Knapsack 构造、抽屉原理
    Educational Codeforces Round 62
    CF908G New Year and Original Order 数位DP
    CF833D Red-Black Cobweb 点分治、树状数组
    Codechef CNTL Counting is life 生成函数
    LOJ2527 HAOI2018 染色 生成函数、二项式反演、NTT
    Luogu4916 魔力环 莫比乌斯反演、组合、生成函数
  • 原文地址:https://www.cnblogs.com/fengchong/p/10420688.html
Copyright © 2011-2022 走看看