Git原理学习笔记-未整理

Git 学习笔记

GitHub浏览器快捷键:
t: 查找

多人协作.png

blob.png

commit_pretty=raw.png

commit.png

commit操作的对象组合过程.png

conflict.png

git_config_list.png

Git_log.png

git_ls-tree_id.png

mywork-twoCommit.png

myWork.png

tag.png

tree.png

先丢一堆图。。就是这么任性

目录
Git对象说明

1.Git对象模型

SHA :所有用来表示项目历史信息的文件,都是通过对对象做SHA1哈希得到的40个字符的对象名来进行索引

与SVN的区别

SVN,CVS:增量文件系统,存储每次提交之间的差异
Git:存储每次提交的文件的全部内容

对象

包括三个部分:类型(对象类型),大小(内容大小),内容
四种类型的对象:blob, tree commit tag

blob: 用来存储数据文件,通常是一个文件
tree: 有点像目录,管理一些tree或者blob
commit: 一个commit只指向一个tree,用来标记项目某个特定时间点的状态,包括一些关于时间点的元数据(时间戳,最近一次提交的作者,指向上次提交的指针等)
tag: 标记某个提交的方法

几乎所有的Git功能都是使用这四个简单的对象模型来完成,就像在本机的文件系统之上构建了一个小的文件系统

1. Blob

git show XX
![blob][]
一块二进制数据,不指向任何东西,没有任何属性,因为blob对象内容全部都是数据,如两个文件在一个目录树(或是一个版本仓库)中有同样的数据内容,那么它们将会共享同一个blob对象。Blob对象和其所对应的文件所在路径、文件名是否改被更改都完全没有关系。

2. Tree

git ls-tree 31adb53
一串直线blob对象或者其他tree对象的指针,一般表示内容之间的目录层次关系。
一个tree对象包括一串(list)条目,每一个条目包括:mode、对象类型、SHA1值 和名字(这串条目是按名字排序的)。它用来表示一个目录树的内容。
(注意:在submodules里,trees对象也可以指向commits对象. 请参见 Submodules 章节)

注意:所有的文件的mode位都是644 或 755,这意味着Git只关心文件的可执行位.

3. Commit

可以用git show -s --pretty=raw 31adb53f48cc43f72ee325cac509bf120357657e查看
指向一个tree对象,并带有相关描述信息

4. Tag

一个标签对象包括一个对象名(译者注:就是SHA1签名), 对象类型, 标签名, 标签创建人的名字("tagger"), 还有一条可能包含有签名(signature)的消息. 你可以用 git cat-file 命令来查看这些信息:

Git目录与工作目录

Git目录:为你的项目存储所有历史和元信息的目录,包括所有对象。
Git工作目录:存储着你现在迁出(checkout)来用来编辑的文件。

Git索引

Git索引是一个在你的工作目录和项目仓库间的暂存区(Staging area),每次commit提交的内容就是当前索引(Index)里的内容

Git Start

1. Git安装

1.从源代码开始安装

2.通过一些应用包来安装
Linux,Mac,windows

2. 安装与初始化

设置名字和email,这些都是提交commit的时候的前签名

$ git config --global user.name "Scott Chacon" $ git config --global user.email "schacon@gmail.com"

git config --list:查看配置信息

  1. 获取git仓库 三种途径
  2. git clone git@gitlab.lukou.com:develop/iLukou.git(配置SSH,Add SSH public key)
  3. git clone http://gitlab.lukou.com/develop/iLukou.git
  4. git init in your project

3.工作流程开始

  1. git add file(添加到file索引) / git commit -a(自动添加索引修改到索引并提交) / 缩写 gaa(git add .)
  2. git commit -m / 缩写 gcmsg xxx
  3. git push originName originBranch / 缩写 gp originName originBranch

4.分支合并

now in branch yyy
git branch 得到当前仓库的所有分支

git branch XXX 创建分支XXX

git checkout XXX (gco) 切换到XXX分支 (checkout 会改index,Workspace ,head to the last commit in XXX,所以需要先commit再co)

git merge xxx 合并xxx到yyy现有分支

git diff if 有冲突,diff来查看冲突,然后解决冲突再commit,commit之后,gitk(这个命令不知用)

git branch -d xxx 删除xxx

reset and checkout

reset
  1. git reset --hard commitID

change head to the commit ID,暂存区,工作区和引用指向的目录树三者一致

  1. git reset (--mixed) commitID

change head to the commitID,暂存区和引用指向的目录树相同,工作区不变

  1. git reset --soft commitID

change head to the commitID,暂存区和工作区不变

checkout
  1. git checkout (commit) paths , commit可选,若省略则工作区与暂存区指向的内容相同,修改工作区,不修改HEAD指针

  2. git checkout branch ,暂存区工作区和branch下上次commit时引用指向的目录树一致,改变HEAD指针,HEAd只有在切换到一个分支时才可以对提交进行跟踪,,否则仍然会进入分离头指针的状态,在分离头指针额状态下的提交并不能被引用关联到,从而可能丢失,所以该命令的主要作用是切换分支.

  3. git checkout 汇总工作区,暂存区和HEAd的差异

  1. git checkout branch -- filename
    维持HEAD的指向不变.用branch所指向的提交中的filename替换暂存区和工作区中相应的文件.会将暂存区和工作区中的filename直接覆盖
撒销一个合并

如果你觉得你合并后的状态是一团乱麻,想把当前的修改都放弃,你可以用下面的命令回到合并之前的状态:

$ git reset --hard HEAD
或者你已经把合并后的代码提交,但还是想把它们撒销:

$ git reset --hard ORIG_HEAD
但是刚才这条命令在某些情况会很危险,如果你把一个已经被另一个分支合并的分支给删了,那么 以后在合并相关的分支时会出错。

快速向前合并

还有一种需要特殊对待的情况,在前面没有提到。通常,一个合并会产生一个合并提交(commit), 把两个父分支里的每一行内容都合并进来。

但是,如果当前的分支和另一个分支没有内容上的差异,就是说当前分支的每一个提交(commit)都已经存在另一个分支里了,git 就会执行一个“快速向前"(fast forward)操作;git 不创建任何新的提交(commit),只是将当前分支指向合并进来的分支

查看git日志

git log

git diff branchA..branchB a到b的工作区改动

git diff branchB 当前工作目录与另一个分支的差别

分布式工作流程

两个分支的修改同一份内容
git pull oringinName branchName
git pull : 从远程分支抓取修改的内容,然后把他合并到当前分支(git fetch + git merge)

将修改推到公共仓库
git push ssh://yourserver.com/~you/proj.git master
和git-fetch命令一样git-push如果命令的执行结果不是"快速向前"(fast forward) 就会报错

Git标签

git tag创建标签制定某个提交
git tag tagName commitID
当这样的一条命令执行后,一个新的对象被添加到Git对象库中,并且标签引用就指向了 一个标签对象,而不是指向一个提交(commit). 这样做的好处就是:你可以为一个标签 打处签名(sign), 方便你以后来查验这是不是一个正确的提交(commit).

下面是一个创建标签对象的例子:

$ git tag -a stable-1 1b2e1d63ff

标签对象可以指向任何对象,但是在通常情况下是一个提交(commit). (在Linux内核代 码中,第一个标签对象是指向一个树对象(tree),而不是指向一个提交(commit)).

忽略文件

vim .gitignore

.gitignor文件同样可以像其它文件一样加到项目仓库里( 直接用 git add .gitignore 和 git commit等命令), 这样项目里的其它开发者也能共享同一套忽略 文件规则。

如果你想忽略规则只对特定的仓库起作用,你可以把这些忽略规则写到你的仓库下 .git/info/exclude文件中,或是写在Git配置变量core.excludesfile中指定的 文件里。

rebase

git checkout -b mywork rogin基于远程分支,创建mywork分支
在分支mywork中,生成两次提交,此时,在origin分支,有其他人生成了两次提交,则两个分支都各自向前进了,出现了分叉,这时,
1.我们可以merge,合并origin分支生成一个新的提交,该提交指向两个父commit

2.也可以rebase,将mywork指向origin的最新提交

这些命令会把你的"mywork"分支里的每个提交(commit)取消掉,并且把它们临时 保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后把"mywork"分支更新 到最新的"origin"分支,最后把保存的这些补丁应用到"mywork"分支上。

当'mywork'分支更新之后,它会指向这些新创建的提交(commit),而那些老的提交会被丢弃。 如果运行垃圾收集命令(pruning garbage collection), 这些被丢弃的提交就会删除。

在rebase的过程中,也许会出现冲突(conflict). 在这种情况,Git会停止rebase并会让你去解决 冲突;在解决完冲突后,用"git-add"命令去更新这些内容的索引(index), 然后,你无需执行 git-commit,只要执行:

$ git rebase --continue
这样git会继续应用(apply)余下的补丁。

在任何时候,你可以用--abort参数来终止rebase的行动,并且"mywork" 分支会回到rebase开始前的状态。

$ git rebase --abort

交互式rebase

你亦可以选择进行交互式的rebase。这种方法通常用于在向别处推送提交之前对它们进行重写。交互式rebase提供了一个简单易用的途径让你在和别人分享提交之前对你的提交进行分割、合并或者重排序。在把从其他开发者处拉取的提交应用到本地时,你也可以使用交互式rebase对它们进行清理。

如果你想在rebase的过程中对一部分提交进行修改,你可以在'git rebase'命令中加入'-i'或'--interactive'参数去调用交互模式。

这个命令会执行交互式rebase操作,操作对象是那些自最后一次从origin仓库拉取或者向origin推送之后的所有提交。

若想查看一下将被rebase的提交,可以用如下的log命令:

git rebase -i origin/master

一旦运行了'rebase -i'命令,你所预设的编辑器会被调用,其中含有如下的内容:

pick fc62e55 added file_size
pick 9824bf4 fixed little thing
pick 21d80a5 added number to log
pick 76b9da6 added the apply command
pick c264051 Revert "added file_size" - not implemented correctly

 Rebase f408319..b04dc3d onto f408319
#
 Commands:
  p, pick = use commit
  e, edit = use commit, but stop for amending
  s, squash = use commit, but meld into previous commit
#
 If you remove a line here THAT COMMIT WILL BE LOST.
 However, if you remove everything, the rebase will be aborted.
#

这些信息表示从你上一次推送操作起有5个提交。每个提交都用一行来表示,行格式如下:

(action) (partial-sha) (short commit message)

1.如果指定进行'pick'操作,git会应用这个补丁,以同样的提交信息(commit message)保存提交。

2.如果指定进行'squash'操作,git会把这个提交和前一个提交合并成为一个新的提交。这会再次调用编辑器,你在里面合并这两个提交的提交信息。所以,如果你(在上一步)以如下的内容离开编辑器:

3.如果指定进行'edit'操作,git会完成同样的工作,但是在对下一提交进行操作之前,它会返回到命令行让你对提交进行修正,或者对提交内容进行修改。

$ git reset HEAD^
$ git add file1
$ git commit 'first part of split commit'
$ git add file2
$ git commit 'second part of split commit'
$ git rebase --continue

4.交互式rebase的最后一个作用是丢弃提交。如果把一行删除而不是指定'pick'、'squash'和'edit'中的任何一个,git会从历史中移除该提交。

交互式添加

git add -i

$>git add -i
           staged     unstaged path
  1:    unchanged        +4/-0 assets/stylesheets/style.css
  2:    unchanged      +23/-11 layout/book_index_template.html
  3:    unchanged        +7/-7 layout/chapter_template.html
  4:    unchanged        +3/-3 script/pdf.rb
  5:    unchanged      +121/-0 text/14_Interactive_Rebasing/0_ Interactive_Rebasing.markdown

*** Commands ***
  1: status   2: update   3: revert   4: add untracked
  5: patch    6: diff     7: quit     8: help
What now> 

我们可以进行数个有用的操作,包括取消文件的暂存(3: revert),加入未跟踪的文件(4: add untracked)和查看差异(6: diff)。这些功能都很易懂。还有一个很“酷”的功能,就是暂存补丁(staging patches)(5: patch)。

储藏

当你正在做一项复杂的工作时, 发现了一个和当前工作不相关但是又很讨厌的bug. 你这时想先修复bug再做手头的工作, 那么就可以用 git stash 来保存当前的工作状态, 等你修复完bug后,执行'反储藏'(unstash)操作就可以回到之前的工作里.
git stach save "work in progress for foo feature"
上面这条命令会保存你的本地修改到储藏(stash)中, 然后将你的工作目录和索引里的内容全部重置, 回到你当前所在分支的上次提交时的状态(git reset --hard HEAD)
after do some debug and git commit -a -m "fixed bug"
you can git stash apply back to your work before

you can run several git stash, to stash your work,
see the stash with git stash list

可以用类似'git stash apply stash@{1}'的命令来使用在队
列中的任意一个'储藏'(stashes). 'git stash clear‘则是用来清空这个队列.

Git树名

不用40个字节长的SHA串来表示一个提交(commit)或是其它git对象, 有很多种名字表示方法. 在Git里,这些名字就叫'树名'(treeish).

Sha短名

以下等价
980e3ccdaac54a0d4de358f3fe5d718027d96aae
980e3ccdaac54a0d4
980e3cc

分支,remote,标签

使用分支,remote,标签来代替sha串名,他们只是指向某个对象的指针,

日期标识符

追踪分支

在Git中,追踪分支是用于联系本地分支和远程分支的,如果你在’追踪分支'(Tracking Branches)上执行推送(push)或拉取(pull)时, 它会自动推送(push)或拉取(pull)到关联的远程分支上.

如果你经常要从远程仓库里拉取(pull)分支到本地,并且不想很麻烦的使用"git pull "这种格式; 那么就应当使用‘追踪分支'(Tracking Branches).

‘git clone‘命令会自动在本地建立一个'master'分支,它是'origin/master'的‘追踪分支’. 而'origin/master'就是被克隆(clone)仓库的'master'分支.

译者注: origin一般是指原始仓库地址的别名.

你可以在使用'git branch'命令时加上'--track'参数, 来手动创建一个'追踪分支'.

git branch --track experimental origin/experimental
当你运行下命令时:

$ git pull experimental
它会自动从‘origin'抓取(fetch)内容,再把远程的'origin/experimental'分支合并进(merge)本地的'experimental'分支.

当要把修改推送(push)到origin时, 它会将你本地的'experimental'分支中的修改推送到origin的‘experimental'分支里, 而无需指定它(origin).

搜索

git grep
git grep -c XXXX 文件名

Git的撤销操作-重置,签出

http://gitbook.liuhui998.com/4_9.html
git revert commitID

Git维护

git gc :压缩历史信息来节约磁盘和内存空间
git fsck :云心一些仓库的一致性检查,有问题就回报告,这项操作也有点耗时, 通常报的警告就是“悬空对象"(dangling objects).“悬空对象"(dangling objects)并不是问题, 最坏的情况只是它们多占了一些磁盘空间. 有时候它们是找回丢失的工作的最后一丝希望)

创建公共仓库Git

假设你个人的仓库在目录 ~/proj. 我们先克隆一个新的“裸仓库“,并且创建一个标志文件告诉git-daemon这是个公共仓库.

$ git clone --bare ~/proj proj.git
$ touch proj.git/git-daemon-export-ok

上面的命令创建了一个proj.git目录, 这个目录里有一个“裸git仓库" -- 即只有'.git'目录里的内容,没有任何签出(checked out)的文件.

下一步就是你把这个 proj.git 目录拷到你打算用来托管公共仓库的主机上. 你可以用scp, rsync或其它任何方式.

  1. 通过git协议导出git仓库

用git协议导出git仓库, 这是推荐的方法.

如果这台服务器上有管理员,TA们要告诉你把仓库放在哪一个目录中, 并且“git:// URL”除仓库目录部分外是什么.

你现在要做的是启动 git daemon; 它会监听在 9418端口. 默认情况下它会允许你访问所有的git目录(看目录中是否有git-daemon-export-ok文件). 如果以某些目录做为 git-daemon 的参数, 那么 git-daemon 会限制用户通过git协议只能访问这些目录.

你可以在inetd service模式下运行 git-daemon; 点击 git daemon 可以查看帮助信息.

  1. 通过http协议导出git仓库

git协议有不错的性能和可靠性, 但是如果主机上已经配好了一台web服务器,使用http协议(git over http)可能会更容易配置一些.

你需要把新建的"裸仓库"放到Web服务器的可访问目录里, 同时做一些调整,以便让web客户端获得它们所需的额外信息.

$ mv proj.git /home/you/public_html/proj.git
$ cd proj.git
$ git --bare update-server-info
$ chmod a+x hooks/post-update

(最后两行命令的解释可以点击这里查看: git update-server-info & githooks.)

拼好了proj.git的web URL, 任何人都可以从这个地址来克隆(clone)或拉取(pull) git仓库内容. 下面这个命令就是例子:

$ git clone http://yourserver.com/~you/proj.git

修改你的历史

交互式洐合是修改单个提交的好方法。

git filter-branch是修改大量提交的好方法

git bisect

二分查找问题分支

git blame

如果你要查看文件的每个部分是谁修改的, 那么 git blame 就是不二选择. 只要运行'git blame [filename]', 你就会得到整个文件的每一行的详细修改信息:包括SHA串,日期和作者:

Git是如何物理存储对象的

所有的对象都以SHA值为索引用gzip格式压缩存储, 每个对象都包含了对象类型, 大小和内容.

Git中存在两种对象 - 松散对象(loose object)和打包对象(packed object).

1. 松散对象

松散对象是一种比较简单格式. 它就是磁盘上的一个存储压缩数据的文件. 每一个对象都被写入一个单独文件中.

如果你对象的SHA值是ab04d884140f7b0cf8bbf86d6883869f16a46f65, 那么对应的文件会被存储在:

GIT_DIR/objects/ab/04d884140f7b0cf8bbf86d6883869f16a46f65
Git使用SHA值的前两个字符作为子目录名字, 所以一个目录中永远不会包含过多的对象. 文件名则是余下的38个字符.

2. 打包对象

另外一种对象存储方式是使用打包文件(packfile). 由于Git把每个文件的每个版本都作为一个单独的对象, 它的效率可能会十分的低. 设想一下在一个数千行的文件中改动一行, Git会把修改后的文件整个存储下来, 很浪费空间.(git GC)

查看Git对象

 git-cat-file -t 54196cc2对象 (-p:对象内容 -t:对象类型)
 git ls-tree 92b8b694 树
  

`

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • git常用命令 GIT常用命令备忘:http://stormzhang.com/git/2014/01/27/gi...
    新篇章阅读 8,456评论 1 26
  • 是因为天生的冒险热血心理?还是周围朋友,游戏朋友的攀比心理? 难道说是在现实中难以满足的虚荣心里? 小玉,小航,可...
    疏影杂记阅读 481评论 1 1
  • 在mybatis的使用中有时候需要传入一个简单参数,又需要对它进行判断,在判断时可以用 _parameter 进行替代
    Hello_豆包阅读 2,103评论 0 0
  • 奈何春夏秋冬 花儿们含情脉脉 公然兜售姿色 唯独你 作茧自缚 囚禁风情 不动声色 甘愿独守寂寞 蜂以为 你是含...
    大贵贵丿阅读 440评论 9 2
  • 她离开了有彼此说悄悄话的窗沿,她离开了我们生活了这些日子的小屋。 2017年10月21日 星...
    一枚少年阅读 708评论 10 50