git
git[1],是一个w:分散式版本控制软件,最初由w:林纳斯·托瓦兹(Linus Torvalds)创作,于2005年以w:GPL释出。
git是用于Linux内核开发的版本控制工具。与w:CVS、w:Subversion一类的集中式版本控制工具不同,它采用了分布式版本库的作法,不需要服务器端软件,就可以运作版本控制,使得源代码的发布和交流极其方便。git的速度很快,这对于诸如Linux内核这样的大项目来说自然很重要。git最为出色的是它的合并追踪(merge tracing)能力。
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。
HEAD
编辑指向当前被检出的代码(checked out code),也就是当前所在的工作分支。一般指向refs下的某文件。
也可以进入"detached HEAD"状态,这时你不在一个本地分支上,而是HEAD直接指向一个提交(commit)而不是一个分支。
config
编辑当前git仓库的配置文档,包含如果在本地仓库管理与存储数据,已知的远程仓库,本地用户信息,其他配置数据。
可用文本编辑器来编译此文档,或者用Git命令config。
description
编辑供仓库浏览器工具使用,包含了当前项目(project)的描述。在非共享仓库中通常不改变。
index
编辑是缓冲(staging)区域。包含了紧凑形式的已经被staged的文件改变信息供下一次commit使用。
info/exclude
编辑用户的个人专用文件,针对仓库的个人副本。
info/refs
编辑如果此文件存在,仓库的每个远程或本地的分支,以及tags,除了在refs/heads与 refs/tags有对应的单个文件外,还在此文件中有对应的一行。适用于大型仓库。
ORIG_HEAD
编辑改变当前分支的commit历史的操作在本文件中保存前一次HEAD的值,以允许从错误中恢复。
包含其它文件的目录
编辑branches
编辑未见使用
hooks
编辑存储钩子的文件夹。包含了git仓库特定事件发生时要运行的脚本。Git给出的脚本,使用扩展名.sample。
logs
编辑存储日志(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
svn
编辑如果需要Git命令svn提交到一个Subversion服务器.
对象
编辑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在内部有个指向当前版本的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 status
与git 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客户端
编辑- GitHub Desktop:可用于第三方Git仓库网站[3]
- Git for Windows
- w:TortoiseGit
- SourceTree
- GitEye
参考文献
编辑- ↑ git - Definition and pronunciation. Oxford Learner's Dictionaries.
- ↑ Gerrit Code Review – Project Configuration File Format
- ↑ Using GitHub for Windows with non-GitHub repositories
外部链接
编辑- git官方网站(英文)
- git快速入门(英文)
- git Man Page(英文)
- git用户手册(英文)
- git Community Book(英文)
- 使用git管理源代码
- git# (gitSharp)(英文)
- GNU Interactive Tools
- git从入门到精通P
- 连猴子都能懂的Git入门指南(正体中文)