zoukankan      html  css  js  c++  java
  • git 进阶命令

    我们知道在git提交环节,存在三大部分:working tree, index file, HEAD

    这三大部分中:

    working tree就是你所工作在的目录,每当你在代码中进行了修改,working tree的状态就改变了。

    index file是索引文件,它是连接working tree和HEAD的桥梁,每当我们使用git add命令来登记后,index file的内

    容就改变了,此时index file就和working tree同步了,每次add都在.git/objects/中产生文件。

    commit是最后的阶段,只有commit了,我们的代码才真正进入了git仓库。我们使用git-commit就是将index file里

    的内容提交到commit中。

    总结一下:

    git diff是查看working tree与index file的差别的。

    git diff –cached是查看index file与HEAD的差别的。

    git diff HEAD是查看working tree和HEAD的差别的。(你一定没有忘记,HEAD代表的是最近的一次commit的信息)

     

    demo:

    git init

    ehco '1'>main.c

    git add . 之后,git会根据main.c生成一个名字7f00,把7f00写入index文件中,

    bogon:test-git lakeslove$ git ls-files --stage 
    100644 7f0040ef82be149f4b9be85e4c838417cdb523de 0    main.c

    同时在.git/objects/中生成blob文件:

    .git/objects//7f

    .git/objects//7f/0040ef82be149f4b9be85e4c838417cdb523de

    git cat-file blob 7f00 ,得到结果是 1

    echo '2'>>main.c

    git add . 之后,git会根据main.c生成一个名字650a,把650a写入index文件中替换7f00,

    bogon:test-git lakeslove$ git ls-files --stage 
    100644 650a4b55331fc68f7716d8072fdaa2d5a7a9cf5e 0    main.c

    同时在.git/objects/中生成blob文件:

    .git/objects//65

    .git/objects//65/0a4b55331fc68f7716d8072fdaa2d5a7a9cf5e

    git cat-file blob 7f00 ,得到结果是 1 2

     此时,head中是refs/heads/master,但实际上heads文件夹下是空的,检查如下:

    bogon:test-git lakeslove$ cat .git/head
    ref: refs/heads/master
    bogon:test-git lakeslove$ cat .git/refs/heads/master
    cat: .git/refs/heads/master: No such file or directory

    执行commit

    bogon:test-git lakeslove$ git commit -m 'first commit'

    此时master出现

    bogon:test-git lakeslove$ cat .git/refs/heads/master
    7f2c3e37a5e2e87dd3eaee210c7435a2edd6be1d

    继续查看.git/objects/,发现多了2个文件,其中一个是head中指向的文件7f2c

    bogon:test-git lakeslove$ find .git/objects/
    .git/objects/
    .git/objects//pack
    .git/objects//info
    .git/objects//65
    .git/objects//65/0a4b55331fc68f7716d8072fdaa2d5a7a9cf5e
    .git/objects//b9
    .git/objects//b9/de56321b0abed0131e19cf8f0c15bd91663279
    .git/objects//7f
    .git/objects//7f/2c3e37a5e2e87dd3eaee210c7435a2edd6be1d
    .git/objects//7f/0040ef82be149f4b9be85e4c838417cdb523de

    查看一下7f2c,发现7f2c是一个commit文件,指向刚刚生成的另一个tree文件b9de

    bogon:test-git lakeslove$ git cat-file -t 7f2c
    commit
    bogon:test-git lakeslove$ git cat-file commit 7f2c
    tree b9de56321b0abed0131e19cf8f0c15bd91663279
    author liuxin <liuxin@i-counting.cn> 1590685131 +0800
    committer liuxin <liuxin@i-counting.cn> 1590685131 +0800
    
    first commit

    查一下tree文件b9de,发现它指向我们第二次add . 生成的blob文件650a,内容是“1 2”

    bogon:test-git lakeslove$ git ls-tree b9de
    100644 blob 650a4b55331fc68f7716d8072fdaa2d5a7a9cf5e    main.c

    于是我们总结一下:

    git add . 之后,git会根据main.c生成一个名字650a(实际上是有几个文件生成几个名字),把650a写入index文件,同时在.git/objects/中生成名字为650a的blob文件,blob文件内容就是main.c 的内容

    git commit 之后,git会在.git/objects/生成一个commit文件和一个tree文件,

    commit文件的内容是tree文件的名字,tree文件的内容是这次根据目录生成的其他tree文件,以及add . 生成的blob文件

    在把commit文件写入head里标注的文件(.git/refs/heads/master(master是分支名))中。

    关于git branch和git checkout branchname

    git branch branchname 用于建立一个名字叫branchname的分支。但是你想过这个分支会根据什么来建么?是根据

    working tree?还是根据index file?还是commit呢?(不卖关子,答案告诉你,是…commit!)

    ps:如果你学有余力,我再告诉你一个信息。在你git branch一个新分支后,在目录.git/refs/heads目录下会多出一个

    新的文件,对应于新分支的名称,用来记录新分支下对应的“最后一次commit的信息”。

    ps:如果你学有余力,我还要告诉你一个信息。当你git branch一个新分支并checkout转移到这个新分支后,.git目录

    下的HEAD文件会相应的改变,它的内容将对应着.git/refs/heads/新分支的名称。

    关于git checkout命令

    情况1:

    如果我们在master新增了代码,执行了git add . ,那么可以直接git checkout -b test1,此时test1可以看到master的代码,

    如果此时在test1把代码commit,再git checkout master时,发现刚刚在master上写的代码没有了。

    我们分析一下这个过程:

    master新增了代码,代码在工作目录下,也写入里index里,也在.git/objects/中生成了blob文件。

    git checkout -b test1之后,复制了index中内容,head中的内容从ref: refs/heads/master变成了ref: refs/heads/test1,而工作目录内容没变。

    此时如果git commit,在.git/objects/中生成了commit文件和tree文件,commit指向这个tree文件,而这个tree文件指向刚刚生成的blob文件,

    把commit文件名写在refs/heads/test1中,那么刚刚写的代码就成了test1分支的代码了。

    当切换回master时,会根据master的head重新恢复master的代码,index和工作目录里的代码自然就没有了。

    此时再在test1分支进行修改刚刚那个文件,不add . ,并git checkout master ,就会出现冲突并报错,导致切换失败。

    原因是此时test1的head中内容(最近一次提交)和master的head中的不一致,如果切换过去,那么git不知道把test1的工作目录里新增的内容放在哪里,所以无法合并。

    clone和pull命令

    git commit -a命令只可以用在已经建立了index file之后,也就是在第一次初始化时,必

    须要使用git add命令来建立index file,否则会报错。

    git是这样设计的:clone的话,是clone远端的当

    前分支。通俗的说,远端当前处在哪个分支,你clone来的就是哪个分支。

    查看远程分支:

    bogon:test-git lakeslove$ git branch -a
    * test1
      remotes/origin/HEAD -> origin/test1
      remotes/origin/master
      remotes/origin/test1
    git pull origin master
    (如果你想拉到本地的dev分支上,首先git checkout -b dev,然后使用git pull origin dev,这样就将本地dev分支与远程origin/dev相绑定了)

    其他拉取远程分支的办法:

    git fetch origin test1:test1_local

    git pull origin test1:test1

     

    比较分支间不同的命令

    git diff master test1 //简单容易记住

    git log -p --left-right master...test1  //可以看到每次提交的不同

    git whatchanged -p master...test1//不建议使用

     

    关于 git reset命令

    1 讲解git reset –soft

    2 讲解git reset –hard

    3 讲解git reset –mixed

    4 讲解git reset

    5 讲解git reset –

     

    你会发现

    git reset –soft HEAD^  之后,git diff返回空,而git diff –cached和git

    diff HEAD会返回有效信息。这说明使用–soft选项后,只回退了commit的信息,而不会回复到index file一级。哈哈,这

    就明了了!你如果想撤销commit,并且只回退commit的信息,那么就用–soft吧!

    而且你可以观察到git reset的意思是“撤销到哪个位置”,。也就是说代码管理者需要在后面的参数中指定一个之前

    的commit位置。如上面提到的HEAD^。

    2 讲解git reset –hard

    有了–soft的试验思路,我想你也应该知道如何测试–hard了。有意思的工作留给你去自己完成吧。我只说结论:

    –hard会完全撤销一个commit,彻底的回复到上一次commit的状态。连working tree的源代码也会完全倒退到上次

    commit之时的状态。所以使用–hard后,git diff,git diff –cached和git diff HEAD都会返回空。

    有了这个–hard好工具,你可以这样做:在当前的current working tree中修改了代码,你可以选择git add或者不

    add,然后使用git reset –hard HEAD命令就可以恢复到修改之前的最初状态了。你修改的代码和git add的信息都会被丢弃。

    这个用法记住它,早晚你会用到它。但往往你会武断的认为git reset只能恢复到之前的commit状态,但你往往想不到git

    reset还可以恢复到当前的HEAD所指定的commit状态。

    3 讲解git reset –mixed

    –mixed选项会撤销最近的一次commit,只保留working tree的源代码级的修改,而index file和commit都会回复到上

    一次commit的状态。所以使用–mixed后,git diff和git diff HEAD会有有效信息的输出,而git diff –cached会输出空。

    4 讲解git reset

    我只需要告诉你–mixed是git reset的默认选项。你应该知道了,git reset和git reset –mixed效果是完全一样的。

    5 讲解git reset –

    如果你想从index file中删除一个已登记的文件,那么就用这个命令。

     

    git show-branch会显示分支名称和其开发日志的内容。分割线上下的列是垂直对应的,

    比如第一行! [master] master-first的!垂直向下是+*++ [master] master-first 的+,

    bogon:test-git lakeslove$ git show-branch
    ! [master] master-first
     * [master_2] m2_1
      ! [second] second1
       ! [second_2] second1
    ----
     *   [master_2] m2_1
      ++ [second] second1
    +*++ [master] master-first
    +(加号)表示所在分支包含此行所标识的commit
    (空格)表示所在分支不包含此行所标识的commit
    -(减号)表示所在分支是经过merge得到的,而所在行的内容即是merge的基本信息。
    *(星号)表示如果需要在某列标识+(加号),且此列为当前分支所在列,那么则将+(加号)转变为*(星号)。

    从上图可以看出,

    从master-first 分支branch出了second分支,second执行commit一次,commit信息为‘second1’,之后second分支branch出了second_2分支,

    之后master-first分支branch出了master_2分支,master_2执行commit一次,commit信息为‘m2_1

    git 备份

    其实备份及恢复过程非常简单,但是如果你不甚了解,可能git会给你一个小小的惊吓~~
    举例来说:
    我用于git管理的项目目录为yaoming,那么备份的话,我只需要将整个yaoming目录拷贝到其他存储设备上即可,你
    使用cp、rsync或者rcp等,都随你。记得查看一下,其中的隐藏目录.git也一定要备份过去。
    当恢复时,只需要将备份在其他设备上的yaoming目录拷贝回来,然后在yaoming目录下运行git-init即可,git很聪
    明的,他知道你是想恢复一个仓库还是想新建一个空仓库。然后,就OK了,您可以继续项目开发了。
    当然如果你不知道执行git-init这一步,信心满满的以为git仓库可以随便挪,那git的报错提示“fatal: Not a git
    repository”,会让你以为你的log、branch等等都付之东流了呢!(其实只是虚惊一场~~)
    

      

    经过测试发现,只要把cp -R xxx xxx2 这样拷贝过去,那么cd xxx2,就可以正常指向git命令,无需再次git init。

    如果非要执行一下git init,结果如下:没啥影响。

    bogon:test-git2 lakeslove$ git init
    Reinitialized existing Git repository in /Users/lakeslove/workspace/learnspace/c/gitlearn/test-git1/test-git2/.git/

    毕竟这本书是一个学生在2009年毕业季找工作时边学边写的,git很多命令已经优化了,凑合看就好。

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    关于celery踩坑
    关于git的分批提交pull requests流程
    SymGAN—Exploiting Images for Video Recognition: Heterogeneous Feature Augmentation via Symmetric Adversarial Learning学习笔记
    AFN—Larger Norm More Transferable: An Adaptive Feature Norm Approach for Unsupervised Domain Adaptation学习笔记
    Learning to Transfer Examples for Partial Domain Adaptation学习笔记
    Partial Adversarial Domain Adaptation学习笔记
    Partial Transfer Learning with Selective Adversarial Networks学习笔记
    Importance Weighted Adversarial Nets for Partial Domain Adaptation学习笔记
    Exploiting Images for Video Recognition with Hierarchical Generative Adversarial Networks学习笔记
    improved open set domain adaptation with backpropagation 学习笔记
  • 原文地址:https://www.cnblogs.com/lakeslove/p/12989040.html
Copyright © 2011-2022 走看看