[TOC]
git的不同
分布式版本控制系统( Distributed Version Control System,简称 DVCS )
git 属于分布式版本控制系统,在这类系统中,像 Git,Mercurial,Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照,而是把原始的代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜 像出来的本地仓库恢复。因为每一次的提取操作,实际上都是一次对代码仓库的完整备份
更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的
直接记录快照,而非差异比较
Git 和其他版本控制系统的主要差别在于,Git 只关心文件数据的整体是否发生变化,而大多数其他系统则只关心文件内容的具体差异。这类系统 (CVS,Subversion,Perforce,Bazaar 等等)每次记录有哪些文件作了更新,以及都更新了哪些行的什么内容,
Git 并不保存这些前后变化的差异数据。实际上,Git 更像是把变化的文件作快照后,记录在一个微型的文件系统中。每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照 的索引。为提高性能,若文件没有变化,Git 不会再次保存,而只对上次保存的快照作一链接。
Git 更像是个小型的文件系统,但它同时还提供了许多以此为基础的超强工具,而不只是一个简单的 VCS
近乎所有操作都是本地执行
因为本地有一个版本库,所以大多数的操作都是在本地进行,而不需要联网保存数据。
时刻保持数据完整性
在保存到 Git 之前,所有数据都要进行内容的校验和(checksum)计算,并将此结果作为数据的唯一标识和索引
24b9da6552252987aa493b52f8696cd6d3b00373
Git 的工作完全依赖于这类指纹字串,所以你会经常看到这样的哈希值。实际上,所有保存在 Git 数据库中的东西都是用此哈希值来作索引的,而不是靠文件名
多数操作仅仅添加数据
常用的 Git 操作大多仅仅是把数据添加到数据库。因为任何一种不可逆的操作,比如删除数据,都会使回退或重现历史版本变得困难重重。在别的 VCS 中,若还未提交更新,就有可能丢失或者混淆一些修改的内容,但在 Git 里,一旦提交快照之后就完全不用担心丢失数据,特别是养成定期推送到其他仓库的习惯的话
文件的三种状态
于任何一个文件,在 Git 内都只有三种状态:已提交(committed),已修改(modified)和已暂存(staged)。已提交表示该文件已经被安全地保存在本地数据库 中了;已修改表示修改了某个文件,但还没有提交保存;已暂存表示把已修改的文件放在下次提交时要保存的清单中。
每个项目都有一个 Git 目录(译注:如果 git clone 出来的话,就是其中 .git 的目录;如果git clone --bare 的话,新建的目录本身就是 Git 目录。),它是 Git 用来保存元数据和对象数据库的地方。该目录非常重要,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里面的数据。
版本库
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
获取帮助
$ git help <verb>
$ git <verb> --help
$ man git-<verb>
常用命令
- git init
- git clone + url
- git add file
- git commit -m "meassage"
- git status
- git log
- git diff
- git branch
- git rm
- git mv
- git checkout
- git remote 管理远程仓库的命令
- git pull
- git push
- git tag
文件的状态周期
git add
作用:
1. 开始跟踪某一文件,即纳入版本管理
2. 添加到暂存区
git status
版本管理时,可以分为两种状态;文件状态和内容状态。
文件状态是从整体上描述,分为已跟踪和未跟踪。
内容状态跟踪文件内容的更新。分为:工作目录,暂存区,提交区。
git diff
帮助文件中的描述如下:
Show changes between the working tree and the index or a tree, changes between the index and a tree, changes between two trees, changes between two blob objects, or changes between two files on disk.
常用的:
* git diff 显示的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。
* git diff --staged 或者git diff --cache 显示已经暂存起来的文件和上次提交时的快照之间的差异
git rm
帮助文档对于git rm的解释
Remove files from the index, or from the working tree and the index. **git rm will not remove a file from just your working directory. (There is no option to remove a file only from the working tree and yet keep it in the index**; use /bin/rm if you want to do that.) The files being removed have to be identical to the tip of the branch, and no updates to their contents can be staged in the index, though that default behavior can be overridden with the -f option. When --cached is given, the staged content has to match either the tip of the branch or the file on disk, allowing the file to be removed from just the index.
git rm 不会仅仅删除工作区中的文件,当暂存区中有该文件时,必须使用-f选项,强制删除,以防误删除文件后丢失修改的内容。
使用git rm --cached 可以只删除暂存区中的文件,而保留工作区中的文件,例如下面:
git rm --cached readme.txt
记住: 已提交的代码无法删除。
删除所有被跟踪,但是在工作目录被删除的文件
git rm $(git ls -files --deleted)
git mv
Git 中对文件改名
git mv file_from file_to
git checkout
Updates files in the working tree to match the version in the index or the specified tree. If no paths are given, git checkoutwill also update HEAD to set the specified branch as the current branch.
git checkout 用版本库里的版本替换工作区的版本,无论工作区是修改还是删除
是将文件内容从暂存区复制到工作目录。
git reset
将当前分治回退到历史某个版本
三种模式,主要是内容是否会恢复到工作目录或者暂存区的区别
git reset --mixed <commit> 默认 回退并将内容复制到暂存区
git reset --soft <commit> 仅仅回退分枝,保留工作区和暂存区不变。
git reset --hard <commit> 回退并将内容复制到工作区和暂存区
git reset和 git checkout
二者的功能相似,以下对其进行区分。
git reset 和git checkout 同时具有两个作用范围: file操作和 commit操作
当命令作用于两个作用范围时,是两个完全不同的操作。
以下是对比总结:
git checkout主要是对工作目录的操作,git reset 主要是对于暂存区的操作。
git reset HEAD --file
将文件内容从上次提交复制到暂存区。
.gitignore
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式。
Git 有它自己的文件模式扩展匹配方式,
仅仅作用于未跟踪的文件
git stash
另外其实还有一个stash区,其主要用于临时的保存相应的工作目录和 暂存区
使用git stash就可以得到一个干净的工作目录。
命令总结
注意的是: 使用git rm 来取消文件的跟踪,以及对内容的撤销。
分支
在 Git 中提交时,会保存一个提交(commit)对象,该对象包含一个指向暂存内容快照的指针,包含本次提交的作者等相关附属信息,包含零个或多个指向该提交对象的父对象指针:首次提交是没有直接祖先的,普通提交有一个祖先,由两个或多个分支合并产生的提交则有多个祖先
一个简单的例子是:
Git 仓库中有五个对象:三个表示文件快照内容的 blob 对象;一个记录着目录树内容及其中各个文件对应 blob 对象索引的 tree 对象;以及一个包含指向 tree 对象(根目录)的索引和其他提交信息元数据的 commit 对象。概念上来说,仓库中的各个对象保存的数据和相互关系看起来
多次提交的结果可能如图:
Git 中的分支,其实本质上仅仅是个指向 commit 对象的可变指针。Git 会使用 master 作为分支的默认名字。在若干次提交后,你其实已经有了一个指向最后一次提交对象的 master 分支,它在每次提交的时候都会自动向前移动。
HEAD
Git 中,它是一个指向你正在工作中的本地分支的指针
远程分支
远程分支(remote branch)是对远程仓库中的分支的索引。它们是一些无法移动的本地分支;只有在 Git 进行网络交互时才会更新。远程分支就像是书签,提醒着你上次连接远程仓库时上面各分支的位置。
我们用 (远程仓库名)/(分支名) 这样的形式表示远程分支。比如我们想看看上次同 origin 仓库通讯时 master 分支的样子,就应该查看origin/master 分支,只有与远程仓库进行通信时,远程分支信息才会发生改变。
分支合并
分支合并 需要使用git merge命令。当要合并到远程分支上时,要记得先拉取远程分支的最新进展。