git[1],是一个w:分布式版本控制软件,最初由w:林纳斯·托瓦兹(Linus Torvalds)创作,于2005年以w:GPL发布。

维基百科中的相关条目:

git是用于Linux内核开发的版本控制工具。与w:CVSw:Subversion一类的集中式版本控制工具不同,它采用了分布式版本库的作法,不需要服务器端软件,就可以运作版本控制,使得源代码的发布和交流极其方便。git的速度很快,这对于诸如Linux内核这样的大项目来说自然很重要。git最为出色的是它的合并追踪(merge tracing)能力。

git简明用法

编辑
主页面:git/git简明用法

实现原理

编辑

git和其他w:版本控制系统(如CVS)有不少的差别,git本身关心文件的整体性是否有改变,但多数的版本控制系统如CVS或w:Subversion系统则在乎文件内容的差异。git拒绝保持每个文件的版本修订关系。因此查看一个文件的历史需要遍历各个history快照;git隐式处理文件更名,即同名文件默认为其前身,如果没有同名文件则在前一个版本中搜索具有类似内容的文件。

每个用户都可有全部开发历史的本地副本,changes从这种本地repository复制给其他开发者。这些changes作为新增的开发分支被导入,可以与本地开发分支合并。

分支是非常轻量级的,一个分支仅是对一个commit的引用。

git是用C语言开发的,以追求最高的性能。git自动完成垃圾回收,也可以用命令git gc --prune直接调用。

git存储每个新创建的object作为一个单独文件。为了压缩存储空间占用, packs操作把很多文件(启发式类似名字的文件往往具有类似内容)使用w:差分压缩入一个文件中(packfile),并创建一个对应的索引文件,指明object在packfile中的偏移值。新创建的对象仍然作为单独文件存在。repacks操作非常费时间,git会在空闲时间自动做此操作。也可用命令git gc来直接启动repack。packfile与索引文件都用SHA-1作为校验和并作为文件名。git fsck命令做校验和的完整性验证。

Git服务器典型listenTCP port 9418.

文件有三种状态:已提交(committed),已修改(modified)和已暂存(staged)。已提交表示该文件已经被安全地保存在本地数据库 中了;已修改表示修改了某个文件,但还没有提交保存;已暂存表示把已修改的文件放在下次提交时要保存的清单中。

内部目录结构

编辑

理解Git的内部目录结构对于理解Git是如何工作的有重要作用。

.
└── .git/
    ├── HEAD
    ├── branches/
    ├── config
    ├── description
    ├── 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/
  • objects:存放git对象

根目录下的专用文件

编辑

COMMIT_EDITMSG

编辑

上一次提交的信息保存在这个文件中。可用文本编辑器处理。

FETCH_HEAD

编辑

最后一次的Git命令fectch的操作信息保存在这里。可用于下次Git命令merge。

指向当前被检出的代码(checked out code),也就是当前所在的工作分支。一般指向refs下的某文件。

也可以进入"detached HEAD"状态,这时你不在一个本地分支上,而是HEAD直接指向一个提交(commit)而不是一个分支。

config

编辑

当前git仓库的配置文档,包含如果在本地仓库管理与存储数据,已知的远程仓库,本地用户信息,其他配置数据。

可用文本编辑器来编译此文档,或者用Git命令config。

description

编辑

供仓库浏览器工具使用,包含了当前项目(project)的描述。在非共享仓库中通常不改变。

是缓冲(staging)区域。包含了紧凑形式的已经被staged的文件改变信息供下一次commit使用。

info/exclude

编辑

用户的个人专用文件,针对仓库的个人副本。

info/refs

编辑

如果此文件存在,仓库的每个远程或本地的分支,以及tags,除了在refs/headsrefs/tags有对应的单个文件外,还在此文件中有对应的一行。适用于大型仓库。

ORIG_HEAD

编辑

改变当前分支的commit历史的操作在本文件中保存前一次HEAD的值,以允许从错误中恢复。

包含其它文件的目录

编辑

branches

编辑

未见使用

存储钩子的文件夹。包含了git仓库特定事件发生时要运行的脚本。Git给出的脚本,使用扩展名.sample

存储日志(reflogs)的文件夹。reflog用于记录那些不保存在提交历史中的事情,如rebases, fast-forward merges, resets等。每个分支有一个reflog。reflog不是仓库的公开部分,它严格特定于局部副本仓库,其信息保留有限时间(确省为两周)。可用于从错误中恢复。

objects

编辑

所有的文件、目录列表、commits的存储之地。

未包装(unpacked)的对象存在其下的几个目录里,多个压缩后的对象的包装在一个包装目录里。自动运行的"git gc"会收集未包装的对象压缩后放入包装目录。

refs/heads

编辑

每个本地分支的head commit对应单个文件。另见info/refs

refs/remotes

编辑

已经定义的每个远程仓库对应一个子目录。在子目录中,每个远程分支定义了一个tip commit。

refs/tags

编辑

Can contain one file defining the commit corresponding to each tag (but see info/refs above). 每个tag的commit对应单个文件。另见info/refs

如果需要Git命令svn提交到一个Subversion服务器.

对象

编辑
 
Git中的数据流与存储级别

Git有两种数据结构:可变的索引(index或stage或cache)用于缓冲工作目录信息与下一次提交的版本信息;不变的、仅追加的对象数据库。

对象数据库包含5类对象:

  • blob:二进制大对象包含了一个文件的全部内容。Blobs没有适当的文件名、时间戳、或其他元数据。一个blob的内部名字是它的内容的hash。
  • tree对象:等效于一棵目录树。包含全部包含的文件路径信息以及文件的模式(mode)、blob或tree对象的ID。tree对象是源树(source tree)的快照。用[[:w:默克树}}实现。由于并不包含目录自身的信息,所以git仓库不记录子目录创建或删除的信息,仅记录所包含的文件。
  • commit对象:指向一棵树表示了commit之后源树的状态。commit对象链接tree对象在一起而成为history。commit对象 包含顶层源目录的tree对象名字、一个时间戳、提交作者信息、log信息、0个或多个父commit对象的名字。
  • tag对象是一个名字指向到一个commit,也可以增加关于另外对象的元数据。它可用于数字签名,以保证特定版本的身份真实。
  • branch对象是一个名字指向到一个commit,对于当前检出的分支,在下一次commit时会自动修改branch对象指向最新的commit。

Blob, tree与commit对象用其内容的SHA-1 hash作为ID。对象放入它的hash值得前两个字符标识的目录中,其余hash字符作为这个对象的文件名。

Git数据库中不变引用的对象将会被垃圾回收清除。Git命令可以创建、移动、删除引用。"git show-ref"列出所有引用。某些引用类型:

  • heads: 引用一个本地对象,是commit的指针。每个head可以指任意一个这样的指针。可以包含任意数量的heads。而"HEAD"(全部大写),仅仅指的是当前有效的head。默认情况下,在每个仓库下都有一个head,叫做master。
  • remotes: 引用远程repository中的一个对象
  • stash: 引用一个还没有committed的一个对象
  • meta: 例如一个bare repository中的一个配置, 用户权限; refs/meta/config名字空间等[2]
  • tags:

提交的拓扑关系

编辑

Git的提交作为图的节点,父子关系作为图的有向边,那么提交历史构成有向无环图(DAG)。

可达性与垃圾收集

编辑

一个commit是可达的如果它被branch、tag、reflog条目指向,或是一个可达commit的父亲。一棵tree是可达的如果它被一个可达的commit指向。一个blob是可达的如果被一棵可达的tree指向。此外的commit/tree/blob对象都是不可达的,通常是aborted commits、删除掉的branches等的结果,白白占了存储空间。

不可达的对象可用git命令gc收回占用存储空间。这通常可自动被调用。

Git 指令参考

编辑
 
Git的操作

Git在内部有个指向当前版本的HEAD指针,表示当前的提交(commit)版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,往上100个版本可以写成HEAD~100。提交(commit)版本也可以用SHA1的hash值表示。

获取和创建项目

编辑
  • 命令git init [repName] 在一个目录下创建指定名字的文件夹或文件夹已存在,并在文件夹中创建一个仓库(repository).
  • 命令git clone git://github.com/schacon/simplegit.git 复制该项目的全部记录到本地;并复制该项目的master分支作为工作文件。

基本快照服务

编辑
  • 命令git add指出下次commit包含哪个文件。即把指定工作文件加入缓存 -A选项将增加工作目录所有的文件。-u选项仅处理缓冲中有的文件。
  • 命令git reset [-q] [<tree-ish>] [--] <paths>…​
  • 命令git reset [commit-object] [--hard] [--soft] [filename]:从分支[commit-object];如果用--soft选项,那么工作目录与缓存都不变;如果不用--soft选项,那么缓冲更改;如果用--hard选项,那么工作目录也更改。如果指定文件,则该文件更改。
  • 命令git commit来创建一个commit object。新的commit object将会把当前的HEAD作为它的父亲。commit执行后,HEAD将会指向新的commit object
  • 命令git commit -A自动提交工作文件夹内所有修改的文件(新建的文件不包含在内)
  • 提交消息Tim Pope writes 第一行不应超出50字符。如需要进一步详细解释,第二行为空行,从第三行开始写,每行不超过72列。使用缩进(hanging indent)。
  • 命令git status列出当前工作文件和HEAD比较,哪些文件发生了改变。文件有三种状态:新的没有被添加的文件(可用git add命令添加)、修改的但是没有被提交的文件、已经被提交的文件
  • 命令git checkout -- <filename>:把工作区内的指定文件恢复回到最近一次git commit或git add时的状态。如果没有--,就变成了“切换到另一个分支”的命令。
  • 命令git reset HEAD <filename>:把指定文件在暂存区的修改回退到工作区,并把指定文件在暂存区的内容恢复回到最近一次git commit时的状态。即把暂存区的修改撤销掉(unstage),重新放回工作区。
  • 命令git revert <commit>:撤销指定的提交所做的改变,这些操作并作为一次新的提交。
    • git log [head1]..[head2]:列出head2和head1和head2的公共祖先之间的更改日志。
    • git reflog:记录了所有的操作历史
  • 命令git mv 文件重命名。等效于git rm –cached orig; mv orig new; git add new
  • 命令git rm <filename>:将文件从缓存区和工作目录删除。 如果要在工作目录中留着该文件,可以使用 git rm --cached
  • 忽略特定文件,针对命令git statusgit add -A (增加所有新文件或修改过的文件)。需要注意的是,用git add [filename]增加到缓冲中的文件或者已经提交的文件,是不能忽略的。为忽略某些文件,可把文件名(可带通配符)写入特定的两个文件之一:
    • .git/info/exclude — 这是用户私有的,不是仓库公开的数据。
    • .gitignore — 由于这是在.git目录之外,它可以被当作普通文件上传到仓库。适合作为项目中所有用户共同遵守的忽略文件的定义。

安装和配置

编辑
  • config
  • help

分支与合并

编辑
  • git branch 查看仓库的所有分支
  • git branch [new-head-name] [reference-to-commit-object]给指定的对象起一个新的名字
  • git checkout -b [new-head-name] 创建一个分支并置为当前工作分支
  • git branch -d [head-name] 删除一个本地分支
  • git push remote_rep :remote_branch_name 删除一个远程分支
  • git branch -r
  • git checkout [head-name]:设置head-name为当前的head,重写目录下面的所有文件,就可以在其上开始新的工作
  • git merge [head-name]:把head-name指定的commit对象合并到当前commit对象
  • git cherry-pick:"复制"一个提交节点并在当前分支做一次完全一样的新提交。
  • git rebase [branch-name] 衍合是合并命令的另一种选择。在[branch-name]重演当前分支的历史,提交历史是线性的。 本质上,这是线性化的自动的 cherry-pick。 --abort删除一个commit。
  • mergetool
  • git log --merge 用于合并冲突
  • git log --graph --oneline --decorate --all [branch_name] ^[exclude_branch_name] 显示一个分支的各个commit的信息
  • git diff --merge 3路diff
  • stash
  • git tag -a [mytag] [my-branch] 创建一个带注解的标签

共享和更新项目

编辑
  • git fetch [remote-alias] 更新/同步本地项目
  • git pull [remote-alias] 相当于fetch加上merge
  • git push [remote-alias] [branch] 分享本地改动。必须是远端分支的fast-forwards才可以上传;否则需要在本地先merge再上传。
  • git push origin :remoteBranchNameToDelete 删除远程分支
  • git remote 管理远程仓库
    • git remote -v 查看远程仓库别名的实际链接地址
    • git remote add [alias] [url] 添加一个远端仓库
    • git remote rm [alias] 删除一个远端
    • git remote show origin
  • submodule

检查和比较

编辑
  • git show <commit>:<filename> 展示某个提交版本的某个文件的内容
  • 命令git diff:列出当前工作目录与当前缓存之间的差别,产生的输出兼容于diff -u的输出。
    • git diff --cached,列出当前缓存与当前commit对象之间的差别
    • git diff HEAD,列出当前工作目录与当前commit对象之间的差别
    • git diff [head1]..[head2]:列出head1 和head2之间的区别
    • git diff [head1]...[head2](中间三个点):列出head1和head2以及他们所有的祖先之间的区别。
  • git format-patch origin/master 创建origin与master之间的patch,产生的输出兼容于diff -u的输出。
  • git am: automatically apply it and save the commit
  • git apply --stat P1.txt
  • git apply --check P1.txt
  • git am < P1.txt
  • git merge-base [branchA] [branchB] 最近的共同祖先提交
  • shortlog
  • describe

修补

编辑
  • bisect
  • blame
  • grep

调试

编辑
  • bisect
  • blame
  • grep

电子邮件

编辑
  • am
  • apply
  • format-patch
  • send-email
  • request-pull

外部系统

编辑
  • svn
  • fast-import

管理

编辑
  • clean
  • gc
  • fsck
  • reflog
  • filter-branch
  • instaweb
  • archive
  • bundle

服务器管理

编辑
  • daemon
  • update-server-info

管道指令

编辑
  • cat-file
  • commit-tree
  • count-objects
  • diff-index
  • for-each-ref
  • hash-object
  • ls-files
  • read-tree
  • rev-list
  • rev-parse
  • show-ref
  • symbolic-ref
  • update-index
  • update-ref
  • verify-pack
  • write-tree

GIT GUI客户端

编辑

参考文献

编辑

外部链接

编辑