• 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很多命令已经优化了,凑合看就好。

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    Java/android下哈希sha1和MD5的实现
    ANDROID SOCKET 开发
    UML补充
    TCP协议中的三次握手和四次挥手(转)
    uva 658 最短路
    uva 11280 最短路
    uva 10246 最短路
    uva 11747,kruskal 并查集
    uva 544 dijkstra
    uva 1395 瓶颈树
  • 原文地址:https://www.cnblogs.com/lakeslove/p/12989040.html
Copyright © 2020-2023  润新知