最近工作经常使用Git,本文重点总结归纳一下git经常使用的命令和用法,以及对git基本原理的理解。
一、Git安装后配置
1.1 用户信息
安装后要做的第一件事就是设置你的用户名和邮箱地址,因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改:
$ git config --global user.name "adonfu"
$ git config --global user.email adon@example.com
- 若使用--global 选项,该命令只需要运行一次,Git 都会使用那些信息;
- 若针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有--global 选项的命令来配置。
1.2 Git配置信息存储在三个不同的位置
- /etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置
若git config 使用选项 --system 时,会从此文件读写配置变量。 - ~/.gitconfig 或 ~/.config/git/config 文件:只针对当前用户
若使用 --global 选项,Git读写此文件。 - .git/config:当前仓库。
每一个级别覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。
1.3 查看配置信息
$ git config --list
二、基本命令
1. 获取Git仓库
有两种方法取得Git项目仓库。
1.1 在现有项目或目录下导入所有文件到Git中
若目录gitCmdTest已创建,执行如下命令:
$ cd gitCmdTest
$ git init
若要初始化一个新的版本库~/gitCmdTest/.git/:
$ git init gitCmdTest
1.2 从一个服务器克隆一个现有的Git仓库
克隆仓库的命令格式是git clone [url]
$ git clone https://github.com/fuyadong/firstProject
在当前目录下创建一个firstProject目录,在这个目录下初始化一个.git文件夹,保存远程仓库的所有数据。
若将远程仓库自定义本地仓库:
$ git clone https://github.com/fuyadong/firstProject myproject
1.3 将文件放入版本库
$ touch file1.py #创建文件file1
$ touch file2.py #创建文件file2
$ git add . #将当前路径下所有修改/新增的文件加入代码库
$ git add file1.py file2.py #单个文件添加
$ git add LICENSE
$ git commit -m 'some message' #提交代码
$ git diff #比较当前修改的文件与之前的区别
$ git status #查看状态
1.4 设置忽略文件
有些文件无需纳入Git 的管理,也不希望它们总出现在未跟踪文件列表。通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。
1.4.1 设置整个项目要忽略的文件
在根目录新建一个文件.gitignore,列出要忽略的文件模式。
$ touch .gitignore
$ echo *.[oa] > .gitignore
$ echo *~ > .gitignore
将.gitignore文件加入版本库并提交。
1.4.2 设置自己项目要忽略的文件
修改.git/info/exclude文件,设置要忽略的文件:
*.[oa]
*~
还可以忽略 log,tmp 或者 pid 目录,以及自动生成的文档等。
1.4.3 .gitignore 的格式规范
格式规范如下:
- 所有空行或者以 # 开头的行都会被 Git 忽略。
- 可以使用标准的 glob 模式匹配。
- 匹配模式可以以(/)开头防止递归。
- 匹配模式可以以(/)结尾指定目录。
- 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
glob 模式是简化的 shell 正则表达式:
- 星号(*)匹配零个或多个任意字符;
- [abc] 匹配任何一个列在方括号中的字符;
- 问号(?)只匹配一个任意字符;
- 在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字;
- 使用两个星号(*) 表示匹配任意中间目录,比如
a/**/z
可以匹配 a/z, a/b/z 或a/b/c/z
等。
不同项目及语言的.gitignore文件列表gitignore
2. 本地操作
2.1 提交操作
使用git add建立跟踪,将修改或新增的文件添加到暂存区:
$ git add file1.py
使用git status查询暂存状态:
$ git status
若不想暂存文件file1.py,运行如下命令撤出暂存区:
$ git reset HEAD file1.py
后悔操作:
$ git reset HEAD^ # 恢复到上一个版本
$ git reset HEAD^ file1.py # 将文件回退到上一个版本
$ git reset -soft HEAD~n # 回退到第n个版本
$ git reset <object key> # 回退到具体的提交对象
$ git reset -hard origin/master # 将本地状态与远程master库一致
将暂存区的内容提交更新:
$ git commit -m 'msg'
提交时记录的是放在暂存区域的快照。任何还未暂存的仍然保持已修改状态,可以在下次提交时纳入版本管理。每一次运行提交操作,都是对你项目作一次快照,以后可以回到这个状态或者进行比较。
若已跟踪的文件被修改,可以使用参数-a将修改的文件暂存并提交:
$ git commit -a -m 'msg'
2.2 移除文件
若要删除已暂存的文件(从暂存区移除):
$ rm file.py
$ git rm file.py
再提交时,文件file.py就不会纳入到版本管理。
若要将已经提交到版本库中的文件移除,但希望保留在当前工作目录中,使用选项--cached
:
$ git rm --cached file.py
手动删除,将文件撤出暂存区:
$ rm file.py
可以使用git status
命名查看状态。
文件重命名操作:
$ git mv filename.py file.py
相对于如下操作:
$ mv filename.py file.py
$ git rm filename.py
$ git add file.py
2.3 工作区文件状态
工作目录下每个文件有两个状态:已跟踪或未跟踪。
- 已跟踪的文件:被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后,它们的状态可能处于未修改,已修改或已放入暂存区。
- 未跟踪文件:除已跟踪的文件以外的所有其它文件。它们既不存在于上次快照的记录中,也没有放入暂存区。
- 初次克隆的仓库,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态。
文件状态变化:
git add 建立跟踪,放入暂存区;
git commit 将暂存区中的文件纳入到版本管理;
2.4 撤消操作
若漏提文件或提交信息写错,可以使用参数--amend重新提交:
$ git commit --amend
示例:
$ git commit -m 'initial commit'
$ git add some_file
$ git commit --amend
最终只有一个提交 - 第二次提交将代替第一次提交的结果。
撤销对文件的修改:
$ git checkout -- file.py
$ git checkout HEAD file.py
$ git checkout HEAD *.py
$ git checkout HEAD .
3. 远程仓库操作
3.1 创建远程仓库
- 可以通过github创建一个远程仓库,使用
git clone
命令克隆版本库。
git clone https://github.com/fuyadong/firstProject
自动添加的配置信息,通过命名git config --list
查看。
- 通过命令行创建版本库:
$ git remote add origin remote_git_server_address
显示远程仓库的名字和URL:
$ git remote -v
3.2 从远程仓库中抓取与拉取
从远程仓库中获得数据:
$ git fetch [remote-name]
若版本库通过git clone
命令获取,仓库名称remote-name默认为origin。
3.3 推送到远程仓库
命令格式:git push [remote-name] [branch-name]
首先确保克隆服务器有写入权限。
$ git push origin master
若版本库使用其他名称pub:
$ git remote add pub https://github.com/fuyadong/firstProject
$ git push -u pub master
-u表示使用某个远程仓库,默认的远程库,设置一次即可。
3.4 查看远程仓库
$ git remote show origin
3.5 远程仓库重命名和移除
$ git remote rename pub publish
$ git remote rm publish
4 分支
Git分支是指向提交对象的可变指针,默认分支名字是master,始终指向最新的提交对象,自动向前移动。与其他分支完全没有区别,由git init
命令默认创建。
特殊指针HEAD:指向工作空间当前所在的本地分支,这样Git就知道当前是在哪个分支上。
4.1 创建分支
$ git branch dev
创建一个新分支dev,并不会自动切换到新分支中去。
查看分支当前所指对象:
$ git log --oneline --decorate
查看分叉历史:
$ git log --oneline --decorate --graph --all
可以看到提交历史、各个分支的指向以及项目的分支分叉情况。
4.2 切换分支
切换到分支dev:
$ git checkout dev
新建并切换分支:
$ git checkout -b dev
4.3 删除分支
$ git branch -d dev
4.4 分支管理
$ git branch # 查看本地分支
$ git branch -r # 查看远程分支
$ git branch -v # 查看每个分支的最后一次提交
查看哪些分支已经合并到当前分支:
$ git branch --merged
查看所有包含未合并工作的分支:
$ git branch --no-merged
4.5 合并分支
将分支dev合并入master分支:
$ git checkout master
$ git merge dev
4.6 解决合并冲突
Git在发生冲突的文件中会加入标准的冲突解决标记,可以手动解决冲突,如下一段内容:
<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> dev:index.html
在======= 的上半部分是HEAD 所指示的版本,即HEAD所在的分支;在 ======= 的下半部分,是dev分支所指示的版本;这是可以选择一部分保留,也可手动解决冲突,然后删除冲突标记。使用git add
命令标记冲突已解决。
4.7 远程分支
4.7.1 跟踪分支
在远程跟踪分支基础上,建立本地分支:
$ git checkout -b dev origin/dev
本地分支dev自动从origin/dev拉取,命令格式:git checkout -b [分支名] [远程名]/[分支名]。
跟踪分支:从一个远程跟踪分支检出一个本地分支会自动创建一个叫做 “跟踪分支”(有时候也叫做 “上游分支”)。 跟踪分支是与远程分支有直接联系的本地分支。
在一个跟踪分支上执行:
git push
命令:Git会自行推断应该向哪个服务器的哪个分支推送数据;
git pull
命令:Git能自动地识别去哪个服务器上抓取、合并到哪个分支。
在执行git clone
时,Git通常会自动创建一个名为master的分支来跟踪origin/master。
4.7.2 查看设置的所有跟踪分支
$ git branch -vv
列出所有本地分支及其每个分支正在跟踪哪个远程分支。
4.7.3 推送分支
$ git push origin master
将master分支推送到远程仓库origin上。
4.7.4 获取服务器数据
$ git fetch
从服务器上抓取本地没有的数据,并不会合并;需要执行git merge
命令。
4.7.5 删除远程分支
$ git push origin --delete remote_branch
5 标签
可以使用打标签功能来标记发布节点,比如发布版本的时候。也可以为某个提交打标签。
5.1 查看标签
$ git tag
$ git tag -l 'v2.0*'
5.2 创建标签
创建附注标签:
$ git tag -a v2.0 -m 'my version 2.0'
通过使用git show
命令可以看到标签信息与对应的提交信息。
轻量标签本质上是将提交校验和存储到一个文件中,没有保存任何其他信息。创建轻量标签,不需要使用-a
、-s
或-m
选项,只需要提供标签名字:
$ git tag v2.0-lw
轻量标签和附注标签区别:
一个轻量标签很像一个不会改变的分支,它只是一个特定提交的引用。
附注标签是存储在Git数据库中的一个完整对象。它们是可以被校验的;其中包含打标签者的名字、电子邮件地址、日期时间和标签信息。通常使用附注标签,这样可以看到以上信息。
5.3 后期打标签
可以为之前的提交打标签:
$ git log --pretty=oneline
$ git tag -a v1.2 8fceb05
$ git show v1.2
5.4 共享标签
默认情况下,git push
命令并不会传送标签到远程仓库服务器上,在创建完标签后你必须显式地推送标签到共享服务器上。
$ git push origin v1.2
将不再远程仓库服务器上的标签全部推送到服务器上:
$ git push origin --tags
根据特定的标签版本创建一个分支:
$ git checkout -b dev v2.0
命令格式:git checkout -b branch tag
三、Git基本原理
Git不仅仅是一个版本控制系统,它同时是一个非常强大且易用的工具,是一个内容寻址文件系统。这里只介绍Git内部的对象,以更好的理解上面的命令。
Git对象
三个对象模型:
- blob对象:保存文件快照
- Tree对象:记录目录结构和blob对象索引
- 提交对象:包含树对象指针和提交信息
提交信息有作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象,而由多个分支合并产生的提交对象有多个父对象。
执行一次git commit
提交操作,Git会先计算每一个子目录的校验和,然后在 Git 仓库中这些校验和保存为树对象。 随后,Git 便会创建一个提交对象,对版本库做一次快照。
可以使用如下命令查询提交信息:
$ git log # 获取提交记录
$ git ls-tree <object key> # 查看指定对象所有信息
$ git cat-file -p <object key> # 获取key对应object的内容,根据object里面的内容,继续探索,访问到所有关联object。
参考资料:
[1]: git book官网 Git Book 。
网友评论