Git版本控制系统结构和命令手册
概述
Git 作为一个强大的开源的分布式版本控制系统,在设计开发时为自己提出了一些目标:效率、简单设计、支持非线性开发、完全的分布式和高效地处理大型项目(如Linux内核),Git的最终实现完成了大部分目标。
分布式版本控制
传统的基于文件/补丁的版本控制的问题:
- 难于维护。
- 集中式,不能并发操作。
- 难于回溯和历史记录查询。
传统的集中式版本控制的问题:
- 单点故障
分布式版本控制的问题:
- 高性能。
- 高效的工作方式。支持分支开发(非线性开发)。
- 离线功能。
- 备份与恢复,数据安全性。
- 极强的可维护性。


Git 是什么
核心模型
Git 是什么?
Git 是完全的分布式版本控制,即每一个客户端都保存项目的全部文件以及历史,即使服务器崩溃,它也可以从任何一个客户端那里获得镜像进行恢复。
Git 将所有数据都抽象为 快照流 (Streams of Snapshots)。和其他版本控制系统基于增量的模型不同。

Git 保证 文件完整性,它对每个文件/目录/提交等数据对象会生成签名校验。这意味着在 Git 不知情的情况下,文件和目录的更改是不可能的(包括重命名文件)。
Git 通常只添加数据。
Git 将文件的状态分为三种:Modified -> Staged -> Commited
版本库
- 文件 - blob
- 目录 - Tree
- 版本 - Commit:每次 commit 代表生成了当前工程库的一个快照,且使用唯一的散列值引用。对库中数据的任何修改都会产生不同的快照,也即不同的散列值。
所有数据,都会生成一个散列值(SHA-1),该值可以用作相关对象的引用以及日后恢复数据时所需的键值。采用这种散列值和这种既定的版本库结构的优势: - 高性能。通过散列值访问数据。
- 冗余度。相同的文件内容只需存储一次。
- 分布式版本号。Commit 的散列输入中包括了作者、日期信息。完全相同的文件和目录下,不同的开发者产生的commit会不同,也就不用担心未来会发生版本冲突。
- 版本库之间的高效同步。用户执行 Push 操作时,只需要传送远程版本库中不存在的对象即可。
- 数据完整性。
分支功能
Git 的杀手级特性是它的分支功能。
参考手册:Git-分支
常用命令
重写历史
手册-重写历史
使用交互式 rebase 命令修改历史:
1 | git rebase -i |
配置工具
git config --global user.name "[name]"git config --global user.email "[email address]"git config --global color.ui autogit config --global core.editor "[vim|emacs]"分支
git branch [branch-name]创建新分支git switch -c [branch-name]切换到指定分支并更新工作目录git merge [branch-name]将指定分支的历史合并到当前分支,git会处理过程中可能会出现的冲突问题。git branch -d [branch-name]删除指定分支git stash储藏当前脏工作目录下的修改;该命令经常用于下面的场景:当想切换到另一个分支修复Bug,但又不想提交当前分支下的修改,这时候可以使用git stash来储存当前修改,后面可以使用git stash pop恢复;另外其储存内容不会git push到服务器。进行更改
git log当前分支的历史git log --follow [file]列出文件的版本历史,包括重命名git diff [first-branch]...[second-branch]两个分支的内容差异git show [commit]显示指定commit的元数据和内容变化git add [file]将文件进行快照处理,即进入staged域git commit -m "[descriptive message]"将文件快照永久地记录在版本历史中重做提交
git reset [commit]撤销所有commit后的提交,在本地保存更改git reset --soft [commit]保留历史,改回指定提交git reset --hard [commit]放弃所有历史,改回指定提交git commit --amend对commit的反悔git reset HEAD <file>...对add命令的撤回git checkout -- <file>对一个Modified的文件撤回修改创建仓库
git init创建新的仓库git remote add origin [url]将本地仓库与远程仓库连接起来git remote show [remote-name]git remote rename改变远程仓库的名字git clone [url]镜像远程仓库到本地标签tag
git tag列出标签git tag -a [tag-name]创建annotated类型的标签,该类型标签比较正式,它指向所有信息git tag [tag-name]创建lightweight类型的标签,不正式,临时指向小部分信息git show [tag-name]显示标签信息git tag -a [tag-name] [commit-checksum]给某次提交添加tag同步更改
git fetch下载远程跟踪分支的全部历史,它只获取本地没有的那部分数据,clone命令封装了fetch命令git push将所有本地分支上传到远程服务器git merge将远端跟踪分支合并到当前本地分支git pull使用来自对应远端分支的所有新提交更新你当前的本地工作分支。git pull是 git fetch 和 git merge 的结合。子模块 :
子模块允许用户将一个git仓库作为另一个git仓库的子目录。它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。
git submodule add [url]
git submodule init初始化本地配置文件
git submodule update该项目中抓取所有数据并检出父项目中列出的合适的提交
git clone --recurse-submodules [url]自动初始化并更新仓库中的每一个子模块, 包括可能存在的嵌套子模块。
git submodule update --remote --initPatching:
git apply --stat xxxx.patch检查 patch 文件git apply --check xxxx.patch检查能否应用成功git am --signoff < xxxx.patch应用补丁调试:
git blame: 追溯一个文件的历史修改记录。
.gitignore文件
Github
使用 wget 下载 github 上的单个文件:
1 | wget -L https://raw.github.com/[user name]/[repositorty name]/[branch]/[file]. |
如果遇到类似下面的错误报告:
1 | wget -L https://raw.github.com/[user name]/[repositorty name]/[branch]/[file]. |
则可以修改 /etc/hosts 文件,使得对 raw.github.com 域名的解析指向国内可以访问的 IP 地址:
1 | /etc/hosts |
术语表
- commit 提交: 一个 Git 对象,是你整个仓库的快照的哈希值
- branch 分支: 一个轻型可移动的 commit 指针
- clone: 一个仓库的本地版本,包含所有提交和分支
- remote 远端: 一个 GitHub 上的公共仓库,所有小组成员通过它来交换修改
- fork: 一个属于另一用户的 GitHub 上的仓库的副本
- pull request 拉取请求: 一处用于比较和讨论分支上引入的差异,且具有评审、评论、集成测试等功能的地方
- HEAD: 代表你当前的工作目录。使用git checkout 可移动 HEAD 指针到不同的分支、标记(tags)或提交。