一、Git介绍
所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。不幸的是,Microsoft的Word格式是二进制格式,因此,版本控制系统是没法跟踪Word文件的改动的。
二、Git工作原理
1. Git几个区域理解
- Workspace:工作区也就是working directory
- Index / Stage:暂存区
- Repository:仓库区(或本地仓库)
- Remote:远程仓库
工作区
是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘
上供你使用或修改。这些文件就是你直接看到的文件
暂存区
.git目录下的index文件, 暂存区会记录git add
添加文件的相关信息(文件名、大小、timestamp…),不保存文件实体, 通过id指向每个文件实体。可以使用git status
查看暂存区的状态。暂存区标记了你当前工作区中,哪些内容是被git管理的。
本地仓库
git commit
后同步index的目录树到本地仓库,方便从下一步通过git push
同步本地仓库与远程仓库的同步。
远程仓库
远程仓库是指托管在因特网或其他网络中的你的项目的版本库,本质和本地仓库相同。
2. 文件状态
你工作目录下的每一个文件都不外乎这两种状态:已跟踪或未跟踪。
- 已跟踪的文件是指那些被纳入了
版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后,它们的状态可能处于未修改,已修改或已
放入暂存区。 - 工作目录中除已跟踪文件以外的所有其它文件都属于未跟踪文件,它们既不存在于上次快照的记
录中,也没有放入暂存区。 新添加一个文件,其就处于未跟踪状态
3. Git分支理解
- Git每次的提交对象都包含上一次提交的指针,故所有提交会形成唯一的链结构。
-
Git 的分支,其实本质上仅仅是指向提交对象的可变指针
- 每个分支都是一个指针,指向某一次提交,例如master指针指向
f30ab
的提交,testing分支指向87ab2
的提交 - 当前分支使用HEAD指针指向,例如切换会master分支,则HEAD就指向master
三、Git常用命令
1. 创建版本库
git clone <url>
克隆远程的版本库到本地,eg:git clone https://github.com/breezenan/getskills.git
git init
初始化一个本地Git仓库,会在当前目录下产生.git
文件夹,然后当前文件夹下的文件就会被git进行管理
2. 修改和提交
git status // 显示
.git
版本库的所有文件状态
git status . // 显示当前文件夹下的文件状态
git diff // 比较工作区和暂存区差异
git diff --cached [<path>...] // 比较暂存区与最新本地版本库(本地库中最近一次commit的内容)
git diff HEAD [<path>...] // 比较工作区与最新本地版本库
git diff commit-id [<path>...] // 比较工作区与指定commit-id的差异
git diff --cached [<commit-id>] [<path>...] // 比较暂存区与指定commit-id的差异
git diff [<commit-id>] [<commit-id>] // 比较两个commit-id之间的差异
git add [<path>...] // 将指定文件或文件夹加入到暂存区。如果该文件是新文件,则新文件由未跟踪状态变为跟踪状态并放入暂存区
git rm <file> // 将指定的已删除文件放入暂存区,或者将指定文件删除并放入暂存区,git add无法将已删除文件加入到暂存区
git rm --cached <file> // 对指定文件不跟踪,但不删除,相当于将指定文件变为新增文件
git commit // 直接提交,会弹出提交信息窗口
git commit -m "your commit info" // 直接提交,-m指定提交信息
git commit --amend // 将最新的提交重新提交,如果暂存区存在快照,也会和本次提交作为一次提交
3. 查看提交历史
git log // 查看提交历史记录
git log <file> // 查看指定文件提交历史(不带具体修改变化)
git log -p <file> // 查看指定文件提交历史(带具体修改变化)
git show <commitid> // 查看指定提交的修改内容
git show <commitid> <file> // 查看指定提交指定文件的修改内容
git show --name-only <commitid> // 查看指定提交修改的文件的文件名
4. 撤销
git checkout -- <file> // 本地修改的(不包含新增)文件还原到仓库状态或暂存状态
git reset HEAD // 把暂存区的修改撤销掉(unstage),重新放回工作区
git reset HEAD <file> // 把暂存区的指定修改文件撤销掉(unstage),重新放回工作区
git reset --hard <commitid> // 回退到指定版本,此时HEAD就指向指定commitid,并且版本内容会完全覆盖工作区,故会导致工作区内容丢失
git revert <commitid> // 将制定提交内容移除(会产生一个新的提交)
git remote
git remote 列出每个远程服务器的简写
nan@breeze:~/work/getskills$ git remote
gitee
origin
git remote -v 列出远程服务
nan@breeze:~/work/getskills$ git remote -v
gitee https://gitee.com/wangyannan/getskills.git (fetch)
gitee https://gitee.com/wangyannan/getskills.git (push)
origin https://github.com/breezenan/getskills.git (fetch)
origin https://github.com/breezenan/getskills.git (push)
提交暂存区内容到仓库
git branch
git branch -v 查看分支,并显示各个分支的最后一次提交
git branch --merged
git branch --no-merged
git branch -d testing
git branch -vv
git checkout
git reset HEAD <file> 取消暂存
git status 查看状态
git status -s 状态简览
git cherry-pick
git merge
fast-forward模式merge
例如仓库如下图,有三个分支master,hotfix,iss53
$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)
由于当前 master 分支所指向的提交是你当前提交(有关 hotfix 的提交)的直接上游,所以 Git 只是简单的将指针向前移动。 换句话说,当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做快进(fast-forward)。
master 被快进到 hotfix
三方合并
例如仓库如下图,有两个分支master和iss53
一次典型合并中所用到的三个快照
出现这种情况的时候,Git 会使用两个分支的末端所指的快照(C4 和 C5
)以及这两个分支的工作祖先(C2),做一个简单的三方合并Git。将此次三方合并的结果做了一个新的快照并且自动创建一个新的提交指向它。 这个被称作一次合并提交,它的特别之处在于他有不止一个父提交。
合并后如下
Git 会自行决定选取哪一个提交作为最优的共同祖先,并以此作为合并的基础
git fetch
基本知识
我们本地的.git文件夹里面对应也存储了git本地仓库master分支的commit ID 和 跟踪的远程分支origin/master的commit ID(可以有多个远程仓库)。那什么是跟踪的远程分支呢,打开git文件夹可以看到如下文件:
.git/refs/head/[本地分支]
.git/refs/remotes/[正在跟踪的分支]
其中head就是本地分支,remotes是跟踪的远程分支,这个类型的分支在某种类型上是十分相似的,他们都是表示提交的SHA1校验和(就是commitID)
git fetch origin 会更新远程服务器的最新提交到本地的远程跟踪分支,会更新.git/refs/remotes/下的文件commitid
通过git merge origin/master 即可将跟踪的远程分支记录合并到本地仓库master分支并更新工作区
git pull
git pull 相当于直接更新了跟踪的远程分支记录并更新了本地仓库提交并进行merge
git rebase
rebase翻译为变基
现在experiment分支以master为基准,合并记录
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
它的原理是首先找到这两个分支(即当前分支 experiment、变基操作的目标基底分支 master)的最近共同祖先 C2,然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件,然后将当前分支指向目标基底 C3, 最后以此将之前另存为临时文件的修改依序应用
如果experiment分支还有C5记录,那么git rebase master后,还会出现C5'。
git stash
git log
git tag
git remote
HEAD意义
首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD
表示当前版本,也就是最新的提交,上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
。
git diff HEAD
-
git diff HEAD -- filename
命令可以查看工作区和版本库里面最新版本的区别
远程仓库
添加远程仓库
git remote add <shortname> <url>
添加一个新的远程 Git 仓库,同时指定一个你可以轻松引用的简
写
nan@breeze:~/work/gitskills$ git remote add origin https://github.com/breezenan/getskills.git
nan@breeze:~/work/gitskills$ git remote
origin
nan@breeze:~/work/gitskills$ git remote -v
origin https://github.com/breezenan/getskills.git (fetch)
origin https://github.com/breezenan/getskills.git (push)
origin当然可以换成其他名字,例如pig,dog,为了容易标识写github也不错,因为该远程仓库就是github托管,如果在码云(gitee)上也有个远程仓库,则可以给其起名为gitee
git push -u origin master 推送提交到指定分支,并设置上游分支对应关系, -u就是--set-upstream
该命令等效于
git push origin master 推送代码到远程名为origin的master分支
git branch --set-upstream-to master origin/master 设置master分支的默认上游远程分支为origin/master
当建立本地分支和上游分支的关系时,就不用指定远程分支了,默认采用上游分支,例如git push
,此时默认推送到origin master分支
clone远程仓库到本地
git clone https://github.com/breezenan/getskills.git
克隆仓库到本地,此时本地的远程仓库名称默认为origin,示意图如下
Git配置
Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位
置:
- /etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置。 如果使用带有 --system 选项的
git config 时,它会从此文件读写配置变量。 - ~/.gitconfig 或 ~/.config/git/config 文件:只针对当前用户。 可以传递 --global 选项让 Git
读写此文件。 - 当前使用仓库的 Git 目录中的 config 文件(就是 .git/config):针对该仓库。
git config --system color.ui "auto" 针对所有用户
git config --global user.name "John Doe" 针对当前用户
git config user.email = ynwang@grandstream.cn 针对当前git仓库
git config --list 查看配置项
git config user.name 查看user.name的值
忽略文件
在工作区根目录创建.gitignore
文件,里面可以配置忽略跟踪的文件类型.例如:
*.[oa]
*.txt
第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件,第二行忽略.txt形式的文件
GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表,你可以在
https://github.com/github/gitignore 找到它.
Git提交模板配置
- 新建模板文件
.git-commit-template.txt
,名字任意,内容例如:
[Bug 101010/INTERNAL/NBF]
Cause: None
Solution: None
Fixed Version:2019-04-20
Branch: Alapca
内容就是你要提交的内容,在你提交时会让你重新编辑这段内容
-
git config commit.template [刚才创建的模板文件全路径]
这个命令只能设置当前分支的提交模板,如果要针对当前用户,加入--global即可 - 设置编辑器
git config --global core.editor [vi|vim] - git commit
参考
- 一篇文章,教你学会Git
- Git教程
- <<Pro Git>>