git 使用指导

使用篇
1. 我们使用的分支
   目前创建了一个ACL_XXX_DEV分支此分支进行开发
2. 查看日志和差异(git log & git diff)
   针对下图
                     A---B---C ACL_XXX_DEV
                    /
               D---E---F---G remotes/origin/ACL_XXX_DEV
    查看两个分支有没有交点    
    git merge-base ACL_XXX_DEV remotes/origin/ACL_XXX_DEV
    上面执行的结果是 E ,后面可以根据该点进行log或rebase操作;
    git log  /*当前分支日志*/
    git log -N /*查看最近N次的LOG日志*/
    git log <branchName> /*其他分支日志*/
    git log --pretty=oneline --graph  /*--pretty=oneline 只有一行, --graph 表示分支历史简单图示*/
    git log --grep=xxx  /*log日志中包含xxx的日志显示*/
    
    显示从上游分支remotes/origin/ACL_XXX_DEV到ACL_XXX_DEV分支的提交log,
    git log remotes/origin/ACL_XXX_DEV..ACL_XXX_DEV
    git log E..C    
    也就是A B C的log,如果当前分支是ACL_XXX_DEV,那么这个分支名称可以省略
    另外ACL_XXX_DEV可以用C hash值替代,remotes/origin/ACL_XXX_DEV 可以用E A^ A~ 替代,效果是一样的
    A^表示A接到的第一父亲 A^2表示第2父亲,在上图中是没有的,一般在分支merge的时候会出现,A~表示A的父亲,A~2表示父亲的父亲,即D
     git diff E ACL_XXX_DEV --stat /*查看 A B C的修改统计 */
     除了--stat 还有 --name-status等其他选项,可以git help diff看下
     git diff A^ A --stat 查看A提交点做了哪些修改
     如果要看具体的,可以通过difftool(内部使用了vimdiff,在设置篇中设置的)
     git difftool A^ A
     如果两个差异比较大,可以指定某个文件的差异
     git difftool A^ A -- code/.../xxx.file

3. git的分支操作:
   1) 创建分支: git checkout -b <branchName> [<start-point>] ,创建一个本地的开发分支,这个分支的HEAD指向start-point,并检出。
      例如创建一个ACL_TOPA的分支,检出点和ACL_XXX_DEV的HEAD一样,并且切换到ACL_TOPA分支
      git co -b ACL_TOPA ACL_XXX_DEV                 (从本地分支ACL_XXX_DEV检出)
      git co -b ACL_TOPA remotes/origin/ACL_XXX_DEV  (从远端分支ACL_XXX_DEV检出)
      上面的只是从一个分支提交点检出分支,并没有建立跟踪关系,如要建立跟踪关系,则需要加 --track参数,这样后面可以直接push和pull
      git co -b ACL_TOPA remotes/origin/ACL_XXX_DEV --track
      加了--track参数的,可以通过git config --list看到有一项  branch.ACL_TOPA.merge=refs/heads/ACL_XXX_DEV
      如果是同名的,则不用加--track参数,也可以进行跟踪,直接进行push 和pull操作
   2) 切换分支: git checkout <branchName>
      git co ACL_TOPA
      本地的文件将切换到该分支下;
   3) 分支共享: git push origin <branchName>.  
        git push origin ACL_XXX_DEV 可以将dev分支的修改推送到服务器。 如果服务器上没有该分支,该命令可以在服务器上新建一个分支。
        在远端服务器上(10.42.119.8)会多了一个ACL_XXX_DEV的共享分支
        在本地也会多了一个remotes/origin/ACL_XXX_DEV的远端分支
   4) 分支删除:
        a. 删除本地的特性分支,执行git branch -d <branchName>   或  git branch -D <branchName>
        b. 将共享到远端的特性分支删除  git push origin :<branchName>
        C. 如果本地的远端分支如remotes/origin/ACL_XXX_TMP分支需要删除,git branch -d -r origin/ACL_XXX_TMP 省略了remotes参数
                   批量删除远端分支 git br -r | grep 3.00.30_B | xargs git br -d -r
   5) 拉取分支的变更,这个只会更新到本地的远端库,不会将变更影响到远端库的本地分支。
        例如 git fetch origin refs/remotes/*:refs/remotes/* 会将远端库origin下面的分支refs/remotes/* 更新到本地库中refs/remotes/*分支
      使用缩略关键字
      git fch
      一些团队内部推送上去的分支,一般没有前缀,拉取不了更新,使用get fetch拉取
      git fetch
      比如共享的ACL_XXX_DEV分支会将更新到本地的remotes/origin/ACL_XXX_DEV 远端分支,但是不会影响本地ACL_XXX_DEV分支;
      执行前
                     A---B---C ACL_XXX_DEV
                    /
               D---E---F---G remotes/origin/ACL_XXX_DEV
      执行后,更新了远端的H I提交
                     A---B---C ACL_XXX_DEV
                    /
               D---E---F---G---H---I remotes/origin/ACL_XXX_DEV

      git update
          新建git update命令,省去反复敲上面两个命令的麻烦。
          在/usr/local/bin/下面新建文件"git-update",将git fch、git fetch两个命令添加到文件中,命令以回车分隔(也就是一个命令一行)。
          修改该文件权限 chmod 777 /usr/local/bin/git-update。

   6)拉取分支的变更,并更新到本地分支;
      上面checkout的时候已经加了--track参数,那么是可以直接pull的,例如先切换到ACL_XXX_DEV本地分支,然后从远端共享库remotes/origin/ACL_XXX_DEV
      拉取更新并合入到本地ACL_XXX_DEV本地分支;
      git co ACL_XXX_DEV
      git pull --rebase
      --rebase选项,为了保持分支提交历史的线性;
      执行前
                     A---B---C ACL_XXX_DEV
                    /
               D---E---F---G remotes/origin/ACL_XXX_DEV
      执行后,更新了远端的H I提交
                                    remotes/origin/ACL_XXX_DEV
                                   /
               D---E---F---G---H---I---A'---B'---C' ACL_XXX_DEV
      如果拉取失败,可以使用git mergetool或windows下的冲突解决工具来解决
   7)推送本地更新到远端共享库供其他小伙伴使用;
      git co ACL_XXX_DEV
      modify...
      commit...
      自己的本地分支不能保证已经包含共享库上的更新,因此在推送前要先更新到本地分支上来;
      git pull --rebase
      git push
      如果没有跟踪的分支,可以指定到某个分支git push origin ACL_XXX_DEV
      
      还是前面的例子,在pull的基础上,push的结果如下,本地分支和本地远端分支指向同一个位置;
               D---E---F---G---H---I---A'---B'---C' ACL_XXX_DEV (remotes/origin/ACL_XXX_DEV)
               
   8)分支変基,git rebase [--onto <newbase>]  [<upstream>] [<branch>]   
        比如将ACL_TOPA上的一段提交移到ACL_XXX_DEV分支上重做一遍;
     git co ACL_TOPA
     modify...
     commit...
     下面几种命令格式达到的效果是一样的;
     git rebase --onto ACL_XXX_DEV  ACL_XXX_DEV ACL_TOPA
     git rebase --onto ACL_XXX_DEV  ACL_XXX_DEV            /*当前分支的名称可以省略,如果rebase的不是当前分支,则不能省略*/
     git rebase --onto ACL_XXX_DEV  E ACL_TOPA             /*上游分支可以有很多表示方法 A^ A~也是可以的*/
     执行前
                     A---B---C ACL_TOPA
                    /
               D---E---F---G ACL_XXX_DEV
     执行后
                             A'--B'--C' ACL_TOPA
                            /
               D---E---F---G ACL_XXX_DEV
    这样可以将改动合入到ACL_XXX_DEV分支,但是ACL_XXX_DEV还是在原来的位置,如果要变动ACL_XXX_DEV头结点位置,
    上面是一个线性历史提交,因此可以直接使用merge进行分支合并,这种方式叫fast-forward方式;
    git co ACL_XXX_DEV
    git merge ACL_TOPA
    merge后,两个分支指向同一个结点
    D---E---F---G---A'---B'---C' (ACL_TOPA)ACL_XXX_DEV
    后面也可以用push将A B C内容推送给到共享库
    
    使用rebase -i选项修改提交节点顺序:
    例如:A---B---C---D1---E1---D2---E2---D3---E3
    需要将D1,D2,D3修改放在一起,E1,E2,E3修改放在一起,可以执行 git rebase -i C
    然后在出现的编辑器中修改提交点顺序,放在最上面的提交点为时间最早的提交,最下面的提交点为时间最晚的提交。保存然后关闭。
    修改后效果:A---B---C---D1---D2---D3---E1---E2---E3
    
    使用rebase -i同样可以将非线性的分支修改为线性的分支。
    例如:A---B---C---D1---D2---D3---M
                     \              /
                      \E1---E2---E3/
    执行后效果:A---B---C---D1---D2---D3---E1---E2---E3
    
   9) git cherry-pick操作
    上面的例子,也可以这样实现:
    git co ACL_XXX_DEV
    git cherry-pick A B C    
     执行前
                     A---B---C ACL_TOPA
                    /
               D---E---F---G ACL_XXX_DEV
     执行后
                     A---B---C ACL_TOPA
                    /
               D---E---F---G---A'---B'---C' ACL_XXX_DEV
    更复杂的可以结合git rev-list来进行;
4. git本地操作:
  1)将修改暂存: git add [-u] <path> , <path>可以是目录,也可以是文件,如果是目录,则迭代添加该目录下所有修改的文件。
    如果使用-u选项,则只添加修改的文件,新增的文件不会被添加
  2)将修改提交到本地仓库: git commit -m <msg>, 该命令将暂存区域的修改提交到本地仓库。如果是提交某个需求的修改,
     要求<msg>格式为 "<EC/RCS单号:故障/需求描述>:修改描述".
  3)丢弃本地的修改: git checkout -- <path>, <path>可以是目录,也可以是文件,如果是目录,则迭代丢弃该目录下所有文件的修改
     现在版本全编或xml make的时候,会自动修改一些受控文件,这些文件可以用git checkout -- . 来把当前目录所有的文件进行恢复
     主要执行前,确保不包含自己未提交的东西(git update-index也可以忽略受控文件的修改,但是在git stash和git checkout的时候操作会有点麻烦)
  4)取消已经暂存的修改:git reset HEAD <path>, <path>可以是目录,也可以是文件,如果是目录,则迭代取消该目录下所有在暂存区文件的修改
  5)如果本地有修改还未提交,但是现在不想提交,想切换到其他分支处理一些事情,处理完成后再回来继续做
    git stash     /*将当前未提交的工作区和暂存区压栈*/
    git co ...
    ...
    git stash pop /*会将栈中保存的修改恢复,同时在栈中删除*/
    
    git stash list /*    会显示栈中的保存的修改,一般像下面的样子*/
    stash@{0}: WIP on ACL_XXX_DEV: 0f8f2e5 #&#XXX LOG
    
    git stash apply stash@{0} /*不删除栈中的修改,应用保存的修改*/
    git diff stash@{0} [ACL_XXX_DEV] /*看下栈中保存的与当前工作目录中的差异 ,也可以加分支名称,也可以用difftool看具体修改*/
   6) 将工作代码切换到之前某个提交点(同时当前分支指针也指向了这个提交点)
    git reset <commit-hash>   /*默认模式是mixed mode,即暂存区会恢复到这个提交,但是工作区不会恢复,因此git status可以看到相对这个提交点的所有提交*/
    git reset --hard <commit-hash> /*hard mode,会将暂存区和工作目录全部恢复到那个提交点*/
    git reset --soft <commit-hash> /*soft mode 暂存区和工作目录都不会恢复到那个提交点*/
    如果将某个提交点的文件检出来
    git co <commit-hash> -- code/.../filename    /*该命令会覆盖当前提交的点的文件*/
    git show <commit-hash>:code/.../filename > code/.../filename_xxx   /*可以保存为别名,此方法用于在某些场合,使用工具对某些非文本文件格式的打开、对比等操作*/
  6)清理工作目录
    git co -- .    /*makeday或xmlmake会修改受控的文件,这个可以恢复下,见本章节3)部分*/
    git clean -df  /*强制删除un-tracked file,但是.gitignore中指定的文件不会被删除,这个命令可用于解决完冲突、编译完,删除非跟踪文件*/
    git cleanall   /*这个做了个别名,实际上是git clean  -dfx -e .gitignore -e klocwork/ ,包括.gitignore中的指定的文件也会被删除,但是-e指定的文件不会被删除
                    这个命令可用于切换大版本,需要将所有的文件删除,但是保留.gitignore文件和klocwork文件*/

5. 使用git生成补丁
  git log --grep=<需求名称> --author=chupenghong -p --binary --reverse >patch,其中--grep用于过滤某个需求提交到log中的标记名称, --author用于指明提交的作者 -p生成补丁格式  --binary对二进制文件生成补丁 --reverse 按时时间顺序反转
  git apply [--check | --reject | --stat | --ignore-whitespace] patchfile 可以在任意目录下应用补丁,--check检查哪些文件打补丁会失败,--reject会在补丁应用失败时生成.rej文件以表明哪些文本块失败了,--stat可以查看补丁中包含哪些文件的修改
                                                                                                    --ignore-whitespace 打补丁时忽略空格,一般在提交打补丁命令时最好加上该选项
                                                                                                    
6. git svn的使用 (参考《git权威指南》 26.4节,我们涉及到更新所有分支的权限问题,实现和这个书上讲的不一致)
     svn副本库的导入就不在赘述,下面讲下如何从git库提交代码到svn

  1. 在10.42.119.8的/home/git/rosngdev 目录 执行git svn fetch 从svn上拉取最新更新到共享库    
     然后在本地机器上执行
     git fch (实际上是git fetch  origin refs/remotes/*:refs/remotes/*) 从共享库获取更新到本地库
     (目前119.8上每一分钟自动git svn fetch一次,一般不需要大家登陆到119.8再执行了,除非点子背一点。。。)
  2. git co -b tmp_ci xxx 创建一个临时分支tmp_ci用于提交,这个临时分支包含你要提交的一些修改
  3. rebase合入rosng_dev分支,在rosng_dev分支上将修改重新做一遍,此时也可以将不想提交的的commit去掉;
     upstream 可以是非同源的
     git rebase –onto rosng_dev <up_stream> [<branchname>]
     如果出现冲突可以使用git mergetool或windows上的工具来解决冲突,解决冲突后,
     git add 冲突的文件
     git rebase --continue
  4. git reset rosng_dev 此处默认使用的--mixed选项,的目的是将HEAD和index暂存区重置,而工作目录的修改保持,
     这样可以给我们一个机会,对那些受控的文件进行剔除,可以用git checkout -- <file>命令;
     另外一个原因是将多个提交点压缩成一个提交点;
  5. git ci -am "<EC/RCS单号:故障/需求描述>:修改描述" 剔除后受控文件后,然后进行提交到tmp_ci分支
  6. 如果修改可能持续一段时间,此时再次获取最新更新
    (目前119.8上每一分钟自动git svn fetch一次,一般不需要大家登陆到119.8再执行了,除非点子背一点。。。)
     10.42.119.8的/home/git/rosngdev 执行
     git svn fetch
     本地机器
     git fch
  7. git svn dcommit 提交修改到svn
  9. 执行成功后,如果有受控的文件,那么需要将受控文件手动再修改下;
  10. git br -d tmp_ci
  另外一种提交方法:
  1. 拉取更新同上
  2. git co -b tmp_ci rosng_dev 从rosng_dev分支创建一个临时分支
  3. git cherry-pick <commit-A> <commit-B> ... 将要合入的提交点以此挑拣过来,如果有多个的话,肯能冲突会多一点
     如果提交点不连续,可以用此方法,也可以结合标准git提交列表git rev-list使用,例如将相同rcs编号xxx的所有提交点都挑拣过来
     git rev-list --reverse <branch> --grep=xxx | git cherry-pick --stdin
     git rev-list --reverse upstream..<branch> --grep=xxx | git cherry-pick --stdin
     --reverse 提交逆序排列,可按合入顺序排序 来理解
  4. git reset rosng_dev 后面的步骤和上面的相同

  备注:无论是rebase还是cherry-pick,你都可以在提交svn前,准备很长时间,当然这不会影响别人合入svn,也无需锁文件
        如果你想在合入svn时冲突少一点,那么可以提前将提交点压缩成一个点,这样可以减少冲突次数

其他技巧拾遗:
1)    git log 默认使用less工具查看日志, less启用了长行截断模式,在日志的一行较长时会被截断。关闭长行截断,可以设置export LESS=FRX. 该设置可放到.bashrc文件中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值