玖叶教程网

前端编程开发入门

从存档的多版本推进聊聊Git分支

从游戏存档聊聊Git版本管理一文中,我们最后得到了两个存档路径。

   m00
  /   \
 m01  m00-1

那我们为什么要两个存档路径呢?
考虑这么一个场景,马里奥到某个地点可以从地面上走,也可以从水管走。这时候我可能想看看从地面走和从水管走有什么区别,此时我就可以在这个分岔路口先存档一下。比如上面的m00,然后我从地面走,保存m01。然后,我再回到m00,从水管走,保存m00-1。

分支

我们分别按照这两条路径继续往下玩,我们先通过下面的指令进入m01存档:

git checkout master

checkout指令前文中我们已经使用过了,它的作用就是用来切换分支或恢复工作树文件的。后面的master就是分支名。当我们初始化了git目录后,默认会创建一个master分支。
因为之前我们的m01存档是在master分支上的,所以我们通过上面的命令切换到master分支,而m01是最新存档,所以目录中的信息就是和m01相同的内容。
我们从这个存档开始玩游戏,假设我们玩到了1-1关:

        ********
       ************
       ####....#.
     #..###.....##....
     ###.......######              
        ...........                
       ##*#######                 1  -  1
    ####*******######              
   ...#***.****.*###....           
   ....**********##.....           
   ....****    *****....           
     ####        ####
   ######        ######

我们通过下面的命令进行存档:

git add player.txt
git commit -m 'm02'

存档完成后,我们再进入到m00-1对应的存档:

git checkout load-00

load-00是另一个分支,是我们在前文中通过switch命令创建的。因为m00-1存档是load-00分支的最新存档,所以默认就读取到了m00-1的存档内容。
我们同样的开始玩游戏,玩了一段时间后,发现也到了1-1关。
此时,我们通过如下命令进行存档:

git add player.txt
git commit -m 'm00-2'

现在我们就得到了下面这样的存档列表:

       m00
      /   \
     m01  m00-1
     /      \
    m02    m00-2

现在,就出现了一个问题。原来我分别从地面上和管道里进行了游戏,但是最后都到了1-1关。如果我继续按照两个存到路径进行游戏的话,相同的关卡我要玩两次。一般玩家肯定不会乐意的,那该怎么办呢?
此时,我们需要将这两条存档路径合并,即到1-1关,两条存档又回到了一条上。git提供了merge来完成这样的需求。

merge

目前我们在load-00分支m00-2存档处,而目前m00-2和m-02存档的关卡实际都是1-1。我们可以通过如下指令将存档合并:

git merge master

merge指令的作用就是将目标分支的内容与当前分支内容进行合并。此处就是将master分支的内容合并到load-00分支上。
执行之后,会出现类似这样的信息:

Merge branch 'master' into load-00
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.

输入:wq退出后,即完成了合并。此时,存档结构看起来像这样:

       m00
      /   \
     m01  m00-1
     /      \
    m02    m00-2
     \        \
      ---Merge branch 'master' into load-00  

master分支和load-00分支在「Merge branch ‘master’ into load-00」处合并了。但是两边分支还有有差异的:

  • load-00分支的最新提交指向的是「Merge branch ‘master’ into load-00」
  • 而master分支的最新提交指向的是m02
    要使得master最新提交也指向「Merge branch ‘master’ into load-00」,你需要执行如下指令:
git checkout master
git merge load-00

你会看到类似下面的信息:

Updating 0266015..a1321a3
Fast-forward

Git直接将游标指向到了「Merge branch ‘master’ into load-00」。

Fast-forward

如果你使用过其它的VCS,比如SVN,你就会发现这里的差别。像SVN在处理合并时,每次都会新增一个提交,如果是这样的话,两个分支永远都不会被合并,一直在执行下面的循环:

Merge branch 'load-00' into master
Merge branch 'master' into load-00
Merge branch 'load-00' into master
Merge branch 'master' into load-00
......

而Git为了避免此类问题,当两边内容一致时,直接移动游标,而不是新增一个提交。

冲突解决

上面合并时并没有出现冲突,当合并时,Git发现无法自动进行合并时,就会提示类似下面的错误:

Auto-merging player.txt
CONFLICT (content): Merge conflict in player.txt
Automatic merge failed; fix conflicts and then commit the result.

打开player.txt,我们可能会看到如下内容:

      ********
       ************
       ####....#.
     #..###.....##....
<<<<<<< HEAD
     ###.......######               
        ...........                 1  -  1
       ##*#######                   
    ####*******######               
   ...#***.****.*###....            
   ....**********##.....           
   ....****    *****....
=======
     ###.......######               
        ...........                 
       ##*#######                   
    ####*******######               
   ...#***.****.*###....           1  -  3 
   ....**********##.....           
   ....****    *****....                            
>>>>>>> master
     ####        ####
   ######        ######

上面和下面的内容出现了冲突,我们需要进行解决。我们需要自行确定需要保留哪些内容,假设我们要保留1-3,那么我们可以选择下面的内容:

        ********
       ************
       ####....#.
     #..###.....##....
     ###.......######              
        ...........                
       ##*#######                 1  -  3
    ####*******######              
   ...#***.****.*###....           
   ....**********##.....           
   ....****    *****....           
     ####        ####
   ######        ######

处理完,通过下面的指令进行存档即可:

git add player.txt
git commit -m 'm00-3'

Cherry-Pick

与merge比较类似的操作是Cherry-Pick。
我们通过reset命令回退一下:

# 回退操作后面细说
git reset --hard HEAD^

然后我们执行如下命令来演示一下Cherry-Pick:

git cherry-pick master

如果出现冲突,通过上面的方法解决一下冲突,提交即可:

git add player.txt
git commit -m 'm00-3'

提交完成后,我们也能类似下面的存档结构:

       m00
      /   \
     m01  m00-1
     /      \
    m02    m00-2
             \
             m00-3

从结构上,我们可以看到明显的差别:

  • merge后两个分支是汇聚到了一点
  • 而Cherry-Pick只是将一个分支的提交拉到了目标分支,你可以理解为又在目标分支进行了对应的提交

总结

本文通过对存档的管理简单梳理了Git的分支及对应的指令操作。
下面,我们来聊一聊存档的回滚。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言