使用git微命令深入理解git工作机制
首先。这篇不是真正意义上的翻译,所以大家在看的时候不要找相应的英文文章相应着看。这篇文章之所以归类为翻译。是由于最開始有一篇英文文章让我对git内部机制有了清楚的认识,它能够说是我git的启蒙老师吧。然后非常久过去后。自己也有了非常多的git项目实践,认为有必要从自己的理解角度(微命令和经常使用命令相应分析)来整理下自己的理解。于是有了这篇博文。
        git是一种管理数据的工具。一种支持高速索引查找数据并管理数据变化的工具。它为数据加入一个头封装为对象块(本文称为git对象)然后保存为文件,并依据数据生成一个SHA值,然后以该值作为文件名称称的依据。SHA值的前2位是文件的文件夹名字,后面的值为文件名称,这样就能非常easy依据SHA查找到数据。同一时候因为SHA的唯一性,一旦文件内容改变,其相应的SHA就会变化。因而非常适合文件变化管理。git总共同拥有四类对象:
blob对象:
该对象是真正的数据对象,它的内容是各种文件的数据内容,比方git项目里的文件数据。
须要注意的是blob对象仅仅是保存数据,并不保存数据的额外信息,比方文件名称。文件大小。
tree对象:
该对象是一种管理对象。它是用来管理对象的对象,其内容指出了该tree包括哪些子对象,tree能够递归的,也就说tree能够包括其它的tree。Tree对象就像linux文件系统里的文件夹一样,文件夹本身是一种文件,仅仅只是文件夹文件的内容是文件夹下的文件信息,文件夹下还有子文件夹。
commit对象:
commit对象是真正直接呈现给git使用者的,它就是我们常常说到的git项目历史记录,我们常常常使用的git show xxx,git log xxx,git check xxx等命令后面接的数字就是commit对象的名字,也就是commit对象相应的SHA值。
commit对象必须有一个tree对象,它本身并不和数据有直接联系。git工具通过它的tree对象找到该commit相应的数据。同一时候和tree对象一样,它能够有自己的父亲commit。这样就形成了git历史单向链表。
tag 对象:
tag对象事实上就是上面三种对象的一种别名表达方式。
从上面的描写叙述我们可知,git对象的名字是SHA值,就是一堆没有规律的长串的字符,用户自然不easy记也记不住。因此git提出了tag对象这样一种对象,它同意用户以他们easy识别的名字来标示上面的任一对象。
有了这些基本概念,我们通过使用git 微命令来具体的认识下这些对象的形式,生成及使用。git微命令是相对
我们平时用的git commit, git addd等命令而言的,微命令做的事情少,能够非常清晰看到每个步骤。
创建新的git项目
我们运行git init后,系统会自己主动帮我们创建一个隐藏文件夹.git,详细内容例如以下:
itleaks@Itleaks:/tmp/test$ git init .
Initialized empty Git repository in /tmp/test/.git/
itleaks@Itleaks:/tmp/test$ tree . -al
.
└── .git
├── branches
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ └── update.sample
├── info
│ └── exclude
├── objects
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
上面的.git/objects是最关键的文件夹。它就是用来保存上面提到的四种对象文件的文件夹。
生成Blob对象
git生成blob对象是使用githash-object来生成,详细操作例如以下:
itleaks@Itleaks:/tmp/test$ echo "itleaks test">test.txt
itleaks@Itleaks:/tmp/test$ git hash-object -w test.txt
be976caf33466b3a9fbc04260139a992e5664b9c itleaks@Itleaks:/tmp/test$ tree . -al
.
├── .git
│ ├── branches
│ ├── config
│ ├── description
│ ├── HEAD
│ ├── hooks
│ │ ├── applypatch-msg.sample
│ │ ├── commit-msg.sample
│ │ ├── post-update.sample
│ │ ├── pre-applypatch.sample
│ │ ├── pre-commit.sample
│ │ ├── prepare-commit-msg.sample
│ │ ├── pre-push.sample
│ │ ├── pre-rebase.sample
│ │ └── update.sample
│ ├── info
│ │ └── exclude
│ ├── objects
│ │ ├── be
│ │ │ └── 976caf33466b3a9fbc04260139a992e5664b9c
│ │ ├── info
│ │ └── pack
│ └── refs
│ ├── heads
│ └── tags
└── test.txt
itleaks@Itleaks:/tmp/test$ find .git/objects/ -type f
.git/objects/be/976caf33466b3a9fbc04260139a992e5664b9c
从上面能够看出,当我们使用hash-object–w生成一个对象后,git会在.git/objects下生一个文件be/ 976caf33466b3a9fbc04260139a992e5664b9c,这个就是SHA值。
有了这个对象的SHA值后。我们能够通过gitcat-file命令来查看该对象的原始数据。
//查看对象类型
itleaks@Itleaks:/tmp/test$ git cat-file -t be976caf33466b3a9fbc04260139a992e5664b9c
blob
//查看对象内容
itleaks@Itleaks:/tmp/test$ git cat-file -p be976caf33466b3a9fbc04260139a992e5664b9c
itleaks test
此时相应的数据对象图例如以下:
到这里,你可能会问,test.txt这个名字的信息保存在哪呢?事实上前面已经提到了。blob对象仅仅存数据(上面的字符串” itleaks test”),并不保存其它额外信息。那这个名字什么时候保存的呢?保存咋哪里呢?这个就是由以下要提到的tree 对象来维护的。
生成Tree对象
上面的操作过后,系统已经存在一个blob对象了。我们能够将该对象加入到一个tree对象里,在加入到tree对象前。必须将该blob对象封装成一个tree 对象的item数据块, 并将该item数据块写到cache里。item数据块的格式是blob对象SHA值+数据文件名称字(test.txt)+文件模式(100644)。这一个过程由git update-index完毕
itleaks@Itleaks:/tmp/test$ git update-index --add --cacheinfo 100644 \
> be976caf33466b3a9fbc04260139a992e5664b9c test.txt
//到此。最终出现了前面提到的test.txt,这里才是我们在git里看到的文件名称
//事实上这里的文件名称也能够填其它名字,git系统并不认识操作系统中的文件名称。仅仅
//知道这里的文件名称,然后其它用户通过git clone 该git项目时,该blob对象相应的数据
//文件会命名为这里指定的名称
itleaks@Itleaks:/tmp/test$ git ls-files
test.txt
//ls-files能够查看cache里的全部blob对象描写叙述
itleaks@Itleaks:/tmp/test$ find .git/objects/ -type f
.git/objects/be/976caf33466b3a9fbc04260139a992e5664b9c
//update-index运行后,并不会添加object
假设有多个数据,能够反复运行上面的命令,将多个blob对象加入到cache中。
然后当用户运行git write-tree的时候,就会生成一个tree对象,并将cache里的全部blob对象的描写叙述数据加入到tree对象的文件中,详细命令例如以下:
itleaks@Itleaks:/tmp/test$ git write-tree
941220dc97574b7dba7b22fdb21333c7227c9603 itleaks@Itleaks:/tmp/test$ find .git/objects/ -type f
.git/objects/be/976caf33466b3a9fbc04260139a992e5664b9c
.git/objects/94/1220dc97574b7dba7b22fdb21333c7227c9603
//新增了一个object文件
itleaks@Itleaks:/tmp/test$ git cat-file -t 941220dc97574b7dba7b22fdb21333c7227c9603
tree
itleaks@Itleaks:/tmp/test$ git cat-file -p 941220dc97574b7dba7b22fdb21333c7227c9603
100644 blob be976caf33466b3a9fbc04260139a992e5664b9c test.txt
//tree对象的内容是描写叙述其管理的blob对象的指向信息
此时相应的数据对象图例如以下:
到此为止。全部的对象都是相对底层的数据对象,git用户通常是不会直接使用的。
然后就该commit对象露面了。
生成commit对象
事实上commit对象,你能够理解成tree对象的扩展。它是用来描写叙述一个tree对象的额外信息的。它相当于是tree对象为用户预留出来的接口。用户通过生成一个commit对象,就能够给一个tree对象打标签,比方用户姓名,描写叙述。时间。详细生成步骤例如以下:
itleaks@Itleaks:/tmp/test$ echo 'initial version' | git commit-tree 941220dc97574b7dba
f7bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
//上面的941220dc97574b7dba就是tree对象的SHA值
itleaks@Itleaks:/tmp/test$ find .git/objects/ -type f
.git/objects/f7/bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
.git/objects/be/976caf33466b3a9fbc04260139a992e5664b9c
.git/objects/94/1220dc97574b7dba7b22fdb21333c7227c9603
//commit也是一个对象
itleaks@Itleaks:/tmp/test$ git cat-file -t f7bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
commit
itleaks@Itleaks:/tmp/test$ git cat-file -p f7bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
tree 941220dc97574b7dba7b22fdb21333c7227c9603
author itleaks <itleaks@126.com> 1403052327 +0800
committer itleaks <itleaks@126.com> 1403052327 +0800 initial version
//commit对象的内容指出了它描写叙述的是哪个tree
此时相应的数据对象图例如以下:
Commit生成后,用户就熟悉了,用户通过经常使用的git show命令就能够非常直接的查看这个commit
itleaks@Itleaks:/tmp/test$ git show f7bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
commit f7bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
Author: itleaks <itleaks@126.com>
Date: Wed Jun 18 08:45:27 2014 +0800 initial version diff --git a/test.txt b/test.txt
new file mode 100644
index 0000000..be976ca
--- /dev/null
+++ b/test.txt
@@ -0,0 +1 @@
+itleaks test
那运行git log呢?
itleaks@Itleaks:/tmp/test$ git log
fatal: bad default revision 'HEAD'
itleaks@Itleaks:/tmp/test$ cat .git/HEAD
ref: refs/heads/master
itleaks@Itleaks:/tmp/test $ tree .git/refs/heads/
.git/refs/heads/ 0 directories, 0 files
系统会提示bad HEAD,这是由于refs/heads/maste文件不存在。
这个就是以下我要讲的git referrence对象。
Ref对象
从名字能够看出来,它就是一个引用,它就是commit对象的别名,它直接以字符串的形式保存一个commit对象的名字,这样用户直接依据ref对象的名字就能够直接找到相应的commit对象,而不用记住一长串SHA字符串。
另外,这里的ref对象就是我们常说说到git branch,一个branch相应一个refs/heads/xx文件。
itleaks@Itleaks:/tmp/test$ echo "f7bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2"
> .git/refs/heads/master
itleaks@Itleaks:/tmp/test$ find .git/objects/ -type f
.git/objects/f7/bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
.git/objects/be/976caf33466b3a9fbc04260139a992e5664b9c
.git/objects/94/1220dc97574b7dba7b22fdb21333c7227c9603
//生成ref并没有新增object
itleaks@Itleaks:/tmp/test$ find .git/refs/ -type f
.git/refs/heads/master
//运行上面的命令生成一个master ref对象后,用户不再须要使用git show SHA值,而是
//直接使用git show name就能够查看commit对象的具体信息
itleaks@Itleaks:/tmp/test$ git show master
commit f7bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
Author: itleaks <itleaks@126.com>
Date: Wed Jun 18 08:45:27 2014 +0800 initial version diff --git a/test.txt b/test.txt
new file mode 100644
index 0000000..be976ca
--- /dev/null
+++ b/test.txt
@@ -0,0 +1 @@
+itleaks test
refs/heads/master生成后,用户最终能够使用gitlog查看了
itleaks@Itleaks:/tmp/test$ git log
commit f7bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
Author: itleaks <itleaks@126.com>
Date: Wed Jun 18 08:45:27 2014 +0800 initial version
此时相应的数据对象图例如以下:
微git操作相应的git经常使用命令
到此,大家预计也看累了吧,可是假设我告诉你上面这么长的操作,用户事实上通过例如以下两条命令能够实现一样的效果,你会不会吃惊啊!
git add test.txt
git commit -sm “initial version”
我们也来看下这两条操作相应的.git内容变化过程
itleaks@Itleaks:/tmp/test$ echo "itleaks test">test.txt
itleaks@Itleaks :/tmp/test$ git add test.txt
itleaks@Itleaks:/tmp/test$ find .git/objects/ -type f
.git/objects/be/976caf33466b3a9fbc04260139a992e5664b9c
itleaks@Itleaks:/tmp/test$ git cat-file -t be976caf33466b3a9fbc04260139a992e5664b9c
blob
itleaks@Itleaks:/tmp/test$ git ls-files
test.txt
从上面能够看出。git add命令会为我们创建blob对象,而且自己主动将该blob对象加入到cache中。更不可思议的是。生成的对象名字be976caf33466b3a9fbc04260139a992e5664b9c和上面的一模一样,为啥。这是由SHA签名生成机制相关---仅仅要数据一致,其产生的SHA一定一样。
itleaks@Itleaks:/tmp/test$ git commit -sm "initial version"
[master (root-commit) 12ca076] initial version
1 file changed, 1 insertion(+)
create mode 100644 test.txt
itleaks@Itleaks:/tmp/test$ find .git/objects/ -type f
.git/objects/12/ca0768b1a7c1f5f8547617af78e13d7263aaba
.git/objects/be/976caf33466b3a9fbc04260139a992e5664b9c
.git/objects/94/1220dc97574b7dba7b22fdb21333c7227c9603 itleaks@Itleaks:/tmp/test$ git cat-file -p 12ca0768b1a7c1f5f8547617af78e13d7263aaba
tree 941220dc97574b7dba7b22fdb21333c7227c9603
author itleaks <itleaks@126.com> 1403098727 +0800
committer itleaks <itleaks@126.com> 1403098727 +0800 initial version Signed-off-by: itleaks <itleaks@126.com>
itleaks@Itleaks:/tmp/test$ git cat-file -p 941220dc97574b7dba7b22fdb21333c7227c9603
100644 blob be976caf33466b3a9fbc04260139a992e5664b9c test.txt
从上面能够看出commit这条命令生成了两个对象:tree对象和commit对象.大家注意没,仅仅有commit对象的SHA值和我们上面不一样,另外两个对象是一样的,为什么?那是由于commit对象的内容中包括时间,两次commit对象生成的时间不一样意味着其内容就不一样,进而其SHA自然不一样。
commit链形成
上面的操作,仅仅生成一个blob对象, 一个tree对象。一个commit对象,还没法看到commit链的形成过程。因此。为了生成链,我们还须要生成另外一个commit对象。
接着实验。
新增文件,并反复上面的操作的。
itleaks@Itleaks:/tmp/test$ echo "second file">2.txt
itleaks@Itleaks:/tmp/test$ git hash-object -w 2.txt
1c59427adc4b205a270d8f810310394962e79a8b
itleaks@Itleaks:/tmp/test$ find .git/objects/ -type f
.git/objects/f7/bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
.git/objects/1c/59427adc4b205a270d8f810310394962e79a8b
.git/objects/be/976caf33466b3a9fbc04260139a992e5664b9c
.git/objects/94/1220dc97574b7dba7b22fdb21333c7227c9603
itleaks@Itleaks:/tmp/test$ git cat-file -t 1c59427adc4b205a270d8f810310394962e79a8b
blob
itleaks@Itleaks:/tmp/test$ git cat-file -p 1c59427adc4b205a270d8f810310394962e79a8b
second file itleaks@Itleaks:/tmp/test$ git ls-files
test.txt
//原来的cache还在,因此仅仅需加入新的blob对象到cache中去
itleaks@Itleaks:/tmp/test$ git update-index --add 2.txt
itleaks@Itleaks:/tmp/test$ git ls-files
2.txt
test.txt itleaks@Itleaks:/tmp/test$ git write-tree
931fdc25cbc3e0afa6e34cf275693ade0daf2c73
itleaks@Itleaks:/tmp/test$ find .git/objects/ -type f
.git/objects/f7/bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
.git/objects/1c/59427adc4b205a270d8f810310394962e79a8b
.git/objects/93/1fdc25cbc3e0afa6e34cf275693ade0daf2c73
.git/objects/be/976caf33466b3a9fbc04260139a992e5664b9c
.git/objects/94/1220dc97574b7dba7b22fdb21333c7227c9603
itleaks@Itleaks:/tmp/test$ git cat-file -t 931fdc25cbc3e0afa6e34cf275693ade0daf2c73
tree
itleaks@Itleaks:/tmp/test$ git cat-file -p 931fdc25cbc3e0afa6e34cf275693ade0daf2c73
100644 blob 1c59427adc4b205a270d8f810310394962e79a8b 2.txt
100644 blob be976caf33466b3a9fbc04260139a992e5664b9c test.txt
//这里能够看出。这个新增的tree对象指向了两个blob对象
接下来就是commit链形成的重点了,在生成commit对象时,有一个-p參数,这个參数用来指示新生成的commit对象的父亲commit的。
以下就来看看带这个參数和没带这个參数的生成的commit对象的区别
不带-p參数时
itleaks@Itleaks:/tmp/test$ echo "second commit"|git commit-tree 931fdc25cbc
2969683f04d3a32af0d6abf97f170190163b72e3 itleaks@Itleaks:/tmp/ test $ git cat-file -p 2969683f0
tree 931fdc25cbc3e0afa6e34cf275693ade0daf2c73
author itleaks <itleaks@126.com> 1403055500 +0800
committer itleaks <itleaks@126.com> 1403055500 +0800 second commit itleaks@Itleaks:/tmp/test$ git show 2969683f04d3a
commit 2969683f04d3a32af0d6abf97f170190163b72e3
Author: itleaks <itleaks@126.com>
Date: Wed Jun 18 09:38:20 2014 +0800 second commit diff --git a/2.txt b/2.txt
new file mode 100644
index 0000000..1c59427
--- /dev/null
+++ b/2.txt
@@ -0,0 +1 @@
+second file
diff --git a/test.txt b/test.txt
new file mode 100644
index 0000000..be976ca
--- /dev/null
+++ b/test.txt
@@ -0,0 +1 @@
+itleaks test itleaks@Itleaks:/tmp/test$ git log 2969683f04d3a
commit 2969683f04d3a32af0d6abf97f170190163b72e3
Author: itleaks <itleaks@126.com>
Date: Wed Jun 18 09:38:20 2014 +0800 second commit
//没带-p參数时,这个新的commit相当于这次commit一下子添加了两个文件 itleaks@Itleaks:/tmp/test$ git log 2969683f04d3a
commit 2969683f04d3a32af0d6abf97f170190163b72e3
Author: itleaks <itleaks@126.com>
Date: Wed Jun 18 09:38:20 2014 +0800 second commit
//这里仅仅有一条commit记录
带-p參数时
itleaks@Itleaks:/tmp/test$ echo "second commit2"|git commit-tree 931fdc25cbc -p f7bde89df6b5d8ea3f
c29d97b2a89c18bdc68f0812749c76fdadd477cf itleaks@Itleaks:/tmp/test$ git cat-file -p c29d97b2a89c1
tree 931fdc25cbc3e0afa6e34cf275693ade0daf2c73
parent f7bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
author itleaks <itleaks@126.com> 1403055858 +0800
committer itleaks <itleaks@126.com> 1403055858 +0800 second commit2 itleaks@Itleaks:/tmp/test$ git show c29d97
commit c29d97b2a89c18bdc68f0812749c76fdadd477cf
Author: itleaks <itleaks@126.com>
Date: Wed Jun 18 09:44:18 2014 +0800 second commit2 diff --git a/2.txt b/2.txt
new file mode 100644
index 0000000..1c59427
--- /dev/null
+++ b/2.txt
@@ -0,0 +1 @@
+second file
//带了-p參数的commit,显示出来的改动仅仅是添加了2.txt文件 itleaks@Itleaks:/tmp/test$ git log c29d97
commit c29d97b2a89c18bdc68f0812749c76fdadd477cf
Author: itleaks <itleaks@126.com>
Date: Wed Jun 18 09:44:18 2014 +0800 second commit2 commit f7bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
Author: itleaks <itleaks@126.com>
Date: Wed Jun 18 08:45:27 2014 +0800 initial version
//这里,能够看到”second commit2"前面的commit是” initial version”。这就是commit链
此次操作后对象图例如以下:
Branch更新
上面新增了两个commit对象后,系统并不会自己主动更新branch的信息。须要用户主动更新,通过update-ref及尅实现。详细实现例如以下:
itleaks@Itleaks:/tmp/test$ git show master
commit f7bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
Author: itleaks <itleaks@126.com>
Date: Wed Jun 18 08:45:27 2014 +0800 initial version diff --git a/test.txt b/test.txt
new file mode 100644
index 0000000..be976ca
--- /dev/null
+++ b/test.txt
@@ -0,0 +1 @@
+itleaks test //brach master还没有更新,接下来更新
itleaks@Itleaks:/tmp/test$ git update-ref refs/heads/master c29d97
itleaks@Itleaks:/tmp/test$ git log
commit c29d97b2a89c18bdc68f0812749c76fdadd477cf
Author: itleaks <itleaks@126.com>
Date: Wed Jun 18 09:44:18 2014 +0800 second commit2 commit f7bde89df6b5d8ea3fa3ccae0e3d53e8a5aa25d2
Author: itleaks <itleaks@126.com>
Date: Wed Jun 18 08:45:27 2014 +0800 initial version
//看到我们上面加入的” second commit2” commit了
此次操作后对象图例如以下:
![]()
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSVRsZWFrcw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
附录:
启蒙git机制英文站点:http://git-scm.com/book/en/Git-Internals-Git-Objects
/********************************
* 本文来自博客 “爱踢门”
* 转载请标明出处:http://blog.csdn.net/itleaks
******************************************/
使用git微命令深入理解git工作机制的更多相关文章
- 理解ClassLoader工作机制
		
package com.ioc; public class Test { public static void main(String[] args) throws ClassNotFoundExce ...
 - 深刻理解HDFS工作机制
		
深入理解一个技术的工作机制是灵活运用和快速解决问题的根本方法,也是唯一途径.对于HDFS来说除了要明白它的应用场景和用法以及通用分布式架构之外更重要的是理解关键步骤的原理和实现细节.在看这篇博文之前需 ...
 - 深入理解ClassLoader工作机制(jdk1.8)
		
ClassLoader 顾名思义就是类加载器,ClassLoader 作用: 负责将 Class 加载到 JVM 中 审查每个类由谁加载(父优先的等级加载机制) 将 Class 字节码重新 ...
 - 【系统之音】WindowManager工作机制详解
		
前言 目光所及,皆有Window!Window,顾名思义,窗口,它是应用与用户交互的一个窗口,我们所见到视图,都对应着一个Window.比如屏幕上方的状态栏.下方的导航栏.按音量键调出来音量控制栏.充 ...
 - 理解Git的工作流程(转)
		
英文原文:Understanding the Git Workflow 如果你不理解Git的设计动机,那你就会处处碰壁.知道足够多的命令和参数后,你就会强行让Git按你想的来工作,而不是按Git自己的 ...
 - 使用plumbing命令来深入理解git add和git commit的工作原理
		
前言: plumbing命令 和 porcelain命令 git中的命令分为plumbing命令和porcelain命令: porcelain命令就是我们常用的git add,git commit等命 ...
 - 【转】使用git、git-flow与gitlab工作
		
转自:http://www.tuicool.com/articles/BZJRj2 使用git.git-flow与gitlab工作 时间 2013-11-02 00:40:39 Axb的自我修养 原 ...
 - git plumbing 更加底层命令解析-深入理解GIT
		
原文: http://rypress.com/tutorials/git/plumbing 本文详细介绍GIT Plumbing--更加底层的git命令,你将会对git在内部是如何管理和呈现一个项目r ...
 - 使用git、git-flow与gitlab工作
		
使用git.git-flow与gitlab工作 1. 摘要 在工作中使用git代替svn也有一段时间了,对于git的一些特性喜爱的同时也一直遇到相同的问题:“这时候应该打什么命令?”.相对于svn或者 ...
 
随机推荐
- 使用SHA1、SHA2双证书进行微软数字签名
			
微软是第一个宣布了SHA-1弃用计划,在2016年之后Windows和IE将不再信任SHA-1证书.正好我们公司的数字签名也到期了,索性就重新申请了sha256和sha1的新数字证书,用来给产品签名. ...
 - JVM调优总结(六)-分代垃圾回收详述2
			
分代垃圾回收流程示意 选择合适的垃圾收集算法 串行收集器 用单线程处理所有垃圾回收工作,因为无需多线程交互,所以效率比较高.但是,也无法使用多处理器的优势,所以此收集器适合单处理器机器.当然,此收集器 ...
 - [zencart教程]zencart外贸建站仿站交流俱乐部
			
[zencart教程]zencart外贸建站仿站交流俱乐部 1.你想自主一天仿做一个精美的zencart 外贸网站; 2.你想自已自主定制精美的psd 图 zencart模板,并把它变成自定义精美 z ...
 - 《C++ Primer Plus》学习笔记1
			
C++ Primer Plus>学习笔记1 第二章.開始学习C++ 1.控制符endl 假设显示字符串时,在字符串中包括换行符,而不是在末尾加上endl,这样能够大大降低输入量:假设是要生成一个 ...
 - static在C和C++中的用法和区别
			
static主要有三个作用: (1)局部静态变量 (2)外部静态变量/函数 (3)静态数据成员/成员函数 前两种C和C++都有,第三种仅在C++中有,下面分别作以下介绍: 一.局部静态变量 在C/C+ ...
 - 最近盯着accesslog看,发现许多奇怪的东东
			
1.spider,各式各样的spider,就像海里的游鱼 有大的,有小的 2.各类探测http代理的spider,比如这种日志 60.173.14.85 - - [03/Sep/2013:09:59: ...
 - Servlet的学习(四)
			
在本篇的Servlet的学习中,主要来学习由使用MyEclipse来开发Servlet的一些小细节. 细节一:在web.xml中可以对同一个Servlet配置多个对外访问路径,并如果在web.xml中 ...
 - Cordys BOP 4平台开发入门实战演练——Webservices开发(0基础)
			
0.文章导读 本文档针对Cordys BOP-4 WS-AppServer基础功能进行验证和高速开发指导.(高级实践文档请參考兴许文档). 0.1.WS-AppServer概述 WS-AppServe ...
 - LeetCode77:Combinations
			
Given two integers n and k, return all possible combinations of k numbers out of 1 - n. For example, ...
 - TensorFlow实现与优化深度神经网络
			
TensorFlow实现与优化深度神经网络 转载请注明作者:梦里风林Github工程地址:https://github.com/ahangchen/GDLnotes欢迎star,有问题可以到Issue ...