Git原理及基本命令

最近工作经常使用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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容

  • 以下内容是我在学习和研究Git时,对Git操作的特性、重点和注意事项的提取、精练和总结,可以做为Git操作的字典,...
    科研者阅读 4,127评论 4 50
  • 以下内容是我在学习和研究Git时,对Git操作的特性、重点和注意事项的提取、精练和总结,可以做为Git操作的字典,...
    科研者阅读 3,525评论 2 19
  • Git是目前最流行的版本管理系统,也是最先进的分布式版本控制系统(distributed version cont...
    pro648阅读 5,700评论 1 17
  • 中国人的【土】在我看来与金钱和发展速度真的没有关系 有这种感慨的原因是,我发现一个在“吃喝住行穿戴用”上如此追求【...
    A调阅读 246评论 2 3
  • 在这本书的扉页上,写着这样一句话。我想读过这本书的各位也早已明了 一把刀的锋刃不容易越过,因此智者说得救之道是很困...
    14广告刘畅阅读 301评论 0 0