zoukankan      html  css  js  c++  java
  • git stash实现原理

    一、git stash的man手册中对该命令的说明

    git需要保存的内容:
    1、本地修改并且已经通过git add添加到缓存区的
    2、本地修改但是还没有添加到缓存区的
    3、可能还包括本地添加但是没有track的

    DISCUSSION
    A stash is represented as a commit whose tree records the state of the working directory, and its first parent is the commit at HEAD when the stash was created. The tree of the
    second parent records the state of the index when the stash is made, and it is made a child of the HEAD commit. The ancestry graph looks like this:

    .----W
    / /
    -----H----I

    where H is the HEAD commit, I is a commit that records the state of the index, and W is a commit that records the state of the working tree.

    二、当前git状态

    当前文件夹中,add.txt文件已经通过git add添加到了暂存区,test.txt文件在本地进行了修改但是还没有添加到暂存区,而untracked.txt是新添加的文件并且还没有通过git add添加到暂存区。其中head中的内容直接指向的就是这个版本库中对test.txt的第一次修改。
    tsecer@harry: git status
    On branch master
    Your branch is based on 'origin/master', but the upstream is gone.
    (use "git branch --unset-upstream" to fixup)

    Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
    new file: add.txt

    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git restore <file>..." to discard changes in working directory)
    modified: test.txt

    Untracked files:
    (use "git add <file>..." to include in what will be committed)
    untracked.txt

    tsecer@harry: cat .git/refs/heads/master
    c4a4b6388fe600fdc3bfde958b6c0dee9ff82b6f
    tsecer@harry:

    三、把当前内容stash

    1、执行stash之后新生成的object

    这里要注意到的是head的内容并没有变化,但是在stash中增加了一个新的文件内容。
    tsecer@harry: git stash -u
    Saved working directory and index state WIP on master: c4a4b63 commit first test.txt
    tsecer@harry: cat .git/refs/heads/master
    c4a4b6388fe600fdc3bfde958b6c0dee9ff82b6f
    tsecer@harry: cat .git/refs/stash
    9610b5ac0053e646ff30b59bdfd30220c60019f3
    tsecer@harry:

    2、生成object的内容

    看下新stash中内容,可以看到stash中对应的是一次提交,它有三个父节点,一个是当前的HEAD提交,
    tsecer@harry: git cat-file -p 9610b5ac0053e646ff30b59bdfd30220c60019f3
    tree b2cb409c5f82d45c6a4df10935f50c385f9154cc
    parent c4a4b6388fe600fdc3bfde958b6c0dee9ff82b6f
    parent e0ebcb0cda7ad9ce49710396c5b2bed54b055b87
    parent f5568b19b7fa78b7fbe593d2f6338e12c1593379
    author tsecer <tsecer@harry> 1593055039 +0800
    committer tsecer <tsecer@harry> 1593055039 +0800

    WIP on master: c4a4b63 commit first test.txt

    stash提交的两个父节点的内容 ,可以看到日志中提示第一个是index文件的内容,从注释上看,这个index文件包含的是当前index内容,其实也就是暂存区stage中的内容,对应的就是已经git add但是没有commit的内容
    tsecer@harry: git cat-file -p e0ebcb0cda7ad9ce49710396c5b2bed54b055b87
    tree 97dea04cf45b6cf424030c30a473fa3421e4b582
    parent c4a4b6388fe600fdc3bfde958b6c0dee9ff82b6f
    author tsecer <tsecer@harry> 1593055039 +0800
    committer tsecer <tsecer@harry> 1593055039 +0800

    index on master: c4a4b63 commit first test.txt
    这个自动生成的提交日志也描述这个地方是本地新添加但是还没有git add的untracked文件。
    tsecer@harry: git cat-file -p f5568b19b7fa78b7fbe593d2f6338e12c1593379
    tree 3cda92c897126e3a8303c6e9007677752d1ff03b
    author tsecer <tsecer@harry> 1593055039 +0800
    committer tsecer <tsecer@harry> 1593055039 +0800

    untracked files on master: c4a4b63 commit first test.txt
    tsecer@harry:

    3、缺少的内容

    这里其实还缺少一个,就是本地修改但是未提交的内容,事实上,由于新生成的提交包括除HEAD外两个父节点,加上这次提交本身,所以总共包含了三个部分,分别对应“已添加” “未跟踪” 和“已修改”三种类型的stash。

    四、详细看下三个提交内容

    1、自动生成的提交本身

    可以看到,它包含了当前工作区中所有修改内容,不管是不是已经通过git add添加到暂存区。
    其树节点为b2cb409c5f82d45c6a4df10935f50c385f9154cc,内容为
    tsecer@harry: git ls-tree b2cb409c5f82d45c6a4df10935f50c385f9154cc
    100644 blob 6f9e7afb3afe34b7896d73dfec5885032997fa69 add.txt
    100644 blob 5664e262760bcfb014eb7dd19a6aa1241cd360f2 test.txt
    tsecer@harry: git cat-file -p 6f9e7afb3afe34b7896d73dfec5885032997fa69
    added to stage
    tsecer@harry: git cat-file -p 5664e262760bcfb014eb7dd19a6aa1241cd360f2
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    00
    11
    22
    33
    44
    55
    66
    77
    88
    99

    2、第一个父节点

    这个节点包含的是当前暂存区index中的完成内容,可以看到,其中保存的test.txt还是首次提交的内容,也就是和HEAD版本中内容一致。
    tsecer@harry: git cat-file -p e0ebcb0cda7ad9ce49710396c5b2bed54b055b87
    tree 97dea04cf45b6cf424030c30a473fa3421e4b582
    parent c4a4b6388fe600fdc3bfde958b6c0dee9ff82b6f
    author tsecer <tsecer@harry> 1593055039 +0800
    committer tsecer <tsecer@harry> 1593055039 +0800

    index on master: c4a4b63 commit first test.txt
    tsecer@harry: git ls-tree 97dea04cf45b6cf424030c30a473fa3421e4b582
    100644 blob 6f9e7afb3afe34b7896d73dfec5885032997fa69 add.txt
    100644 blob 8b1acc12b635c26f3decadeaa251729d3ce512e9 test.txt
    tsecer@harry: git cat-file -p 6f9e7afb3afe34b7896d73dfec5885032997fa69
    added to stage
    tsecer@harry: git cat-file -p 8b1acc12b635c26f3decadeaa251729d3ce512e9
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9

    3、第二个父节点

    这个包含的是本地新添加的但是没有通过add添加到暂存区的文件,这个是git stash的-u选项生成。
    tsecer@harry: git cat-file -p f5568b19b7fa78b7fbe593d2f6338e12c1593379
    tree 3cda92c897126e3a8303c6e9007677752d1ff03b
    author tsecer <tsecer@harry> 1593055039 +0800
    committer tsecer <tsecer@harry> 1593055039 +0800

    untracked files on master: c4a4b63 commit first test.txt
    tsecer@harry: git ls-tree 3cda92c897126e3a8303c6e9007677752d1ff03b
    100644 blob d1b880281d1432605cc99b212557c85518f703b5 untracked.txt
    tsecer@harry: git cat-file -p d1b880281d1432605cc99b212557c85518f703b5
    untrack
    tsecer@harry:

    五、源代码中的数据结构

    其中的w对应的就是stash文件中显示的内容,b_commit对应HEAD中内容,i_commit对应当前暂存区index内容,w_tree则对应当前工作目录中文件内容。
    git-masteruiltinstash.c
    /*
    * w_commit is set to the commit containing the working tree
    * b_commit is set to the base commit
    * i_commit is set to the commit containing the index tree
    * u_commit is set to the commit containing the untracked files tree
    * w_tree is set to the working tree
    * b_tree is set to the base tree
    * i_tree is set to the index tree
    * u_tree is set to the untracked files tree
    */
    struct stash_info {
    struct object_id w_commit;
    struct object_id b_commit;
    struct object_id i_commit;
    struct object_id u_commit;
    struct object_id w_tree;
    struct object_id b_tree;
    struct object_id i_tree;
    struct object_id u_tree;
    struct strbuf revision;
    int is_stash_ref;
    int has_u;
    };

  • 相关阅读:
    存储过程中Like没有数据?
    鼠标放上图片移动,字体移动
    Excel
    参数无效。区域性ID2155(0X086B)不是受支持的区域性
    JVM指令集及各指令的详细使用说明[转的]
    BTrace使用简介
    ST表
    树剖模板
    AjaxControlToolkit中的CalendarExtender被遮挡及日期格式本地化解决方法
    Using Beyond Compare with TFS
  • 原文地址:https://www.cnblogs.com/tsecer/p/13235327.html
Copyright © 2011-2022 走看看