git简要学习

1.0 Git基础

Git 更像是把数据看作是对小型文件系统的一组快照。 每次你提交更新,或在 Git 中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。 为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个快照流。如下图所示

Git快照流

Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。SHA-1 散列(hash,哈希),这是一个由 40 个十六进制字符(0-9 和 a-f)组成字符串

三种状态

文件在git中有3种状态,已提交(committed),已修改(modified),已暂存(staged),对应了git中的三个工作区域概念:
git仓库,工作区域,暂存区域。见图:

git工作区域划分

Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,拷贝的就是这里的数据。

工作目录是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。

暂存区域是一个文件,保存了下次将提交的文件列表信息,一般在 Git 仓库目录中。 有时候也被称作“索引”,不过一般说法还是叫暂存区域。

基本的 Git 工作流程如下:

1.在工作目录中修改文件。

2.暂存文件,将文件的快照放入暂存区域。

3.提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。

忽略文件

在master目录下编辑.gitignore文件可以添加需要忽略的文件,.gitignore文件规范为:

  • 所有空行或者以 开头的行都会被 Git 忽略。

  • 可以使用标准的 glob 模式匹配。

  • 匹配模式可以以(/)开头防止递归。

  • 匹配模式可以以(/)结尾指定目录。

  • 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号(*)匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。 使用两个星号(*) 表示匹配任意中间目录,比如a/**/z 可以匹配 a/z, a/b/za/b/c/z等。
例子:

# no .a files
*.a

# but do track lib.a, even though you're ignoring .a files above
!lib.a

# only ignore the TODO file in the current directory, not subdir/TODO
/TODO

# ignore all files in the build/ directory
build/

# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt

# ignore all .pdf files in the doc/ directory
doc/**/*.pdf</pre>

git diff

  • git diff --color-words 或者 git diff --word-diff 可以显示具体哪些词发生了变化。
  • git diff : Changes in the working tree not yet staged for the next commit. 显示还没有staged的部分的变化。add 之后就放入stage了。
  • git diff --cached: Changes between the index and your last commit; what you would be committing if you run "git commit" without "-a" option. staged的部分与上次commit之间的差异。如果运行git commit会提交这部分。
  • git diff HEAD: Changes in the working tree since your last commit; what you would be committing if you run "git commit -a" . 当前工作路径下与上次COMMIT的差异,如果运行git commit -a会提交这些更改。

git add

git add 执行之后会对修改过的文件照一个快照(snapshot), 然后把内容stage,并建立索引,以便commit的时候提交。

git commit

  • git commit -a: 相当于git add; git commit -m

移除文件 git rm

git rm 命令已跟踪文件清单中移除并连带从工作目录中删除指定的文件。
如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f(译注:即 force 的首字母)。 这是一种安全特性,用于防止误删还没有添加到快照的数据,这样的数据不能被 Git 恢复。

另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。 当你忘记添加 .gitignore文件,不小心把一个很大的日志文件或一堆 .a 这样的编译生成文件添加到暂存区时,这一做法尤其有用。 为达到这一目的,使用 --cached 选项:
移除暂存区文件:
git rm --cached README

git rm 命令后面可以列出文件或者目录的名字,也可以使用 glob 模式。 比方说:

git rm log/\*.log

**注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开。
**

移动文件

命令git mv file_from file_to相当于以下三条命令:

mv file_from file_to
git rm file_from
git add file_to

有时候用其他工具批处理改名的话,要记得在提交前删除老的文件名,再添加新的文件名。

git log

  • git log : 查看各次commit的信息,最新的在最上面。
  • git log --oneline 可以查看简化版本,在一行内显示
  • git log --stat 列出了详细的信息。
  • git log --patch|-p更为详细的信息,还可以添加-2参数以获得最近2个commit的对比。
  • git log --graph 以图形形式显示
  • git log --pretty,后面可以跟oneline,format(后跟指定格式),例如:
    git log --pretty=oneline, git log --pretty=format:"%h %s"
选项 说明
%H 提交对象(commit)的完整哈希字串
%h 提交对象的简短哈希字串
%T 树对象(tree)的完整哈希字串
%t 树对象的简短哈希字串
%P 父对象(parent)的完整哈希字串
%p 父对象的简短哈希字串
%an 作者(author)的名字
%ae 作者的电子邮件地址
%ad 作者修订日期(可以用 --date= 选项定制格式)
%ar 作者修订日期,按多久以前的方式显示
%cn 提交者(committer)的名字
%ce 提交者的电子邮件地址
%cd 提交日期
%cr 提交日期,按多久以前的方式显示
%s 提交说明

可以接受的格式为:

选项 说明
%H 提交对象(commit)的完整哈希字串
%h 提交对象的简短哈希字串
%T 树对象(tree)的完整哈希字串
%t 树对象的简短哈希字串
%P 父对象(parent)的完整哈希字串
%p 父对象的简短哈希字串
%an 作者(author)的名字
%ae 作者的电子邮件地址
%ad 作者修订日期(可以用 --date= 选项定制格式)
%ar 作者修订日期,按多久以前的方式显示
%cn 提交者(committer)的名字
%ce 提交者的电子邮件地址
%cd 提交日期
%cr 提交日期,按多久以前的方式显示
%s 提交说明

当format与graph命令结合时很有用
git log --pretty=format:"%h %s" --graph

撤销操作

重新提交

有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,可以运行带有 --amend 选项的提交命令尝试重新提交:例如,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作:

git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend

最终你只会有一个提交 - 第二次提交将代替第一次提交的结果

取消暂存的文件

例如,你已经修改了两个文件并且想要将它们作为两次独立的修改提交,但是却意外地输入了 git add * 暂存了它们两个。 如何只取消暂存两个中的一个呢?
git reset HEAD filename

远程仓库使用

git remote -v 显示远程仓库列表
git fetch [remote-name] 将远程仓库内容拉取到本地,它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。
git pull [remote-name] 将远程仓库内容拉取到本地,并进行合并到当前分支。
git push [remote-name] [branch-name] 将分支推送到远程
只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。 当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先将他们的工作拉取下来并将其合并进你的工作后才能推送。
git remote show [remote-name] 会显示远程的更多信息,同样会列出远程仓库的 URL 与跟踪分支的信息。

打标签

使用打标签的方式来记录重要的发布节点
git tag 列出标签
git使用两种标签,轻量(lightweight)标签和附注(annotated)标签,推荐使用annotated标签,信息比较多。
git tag -a v1.54 -m "my version v1.54" 打annotated标签
git shown v1.54 显示tag的信息

后期打标签

git tag -a v1.2 9fceb02 只需要后面跟部分校验码就可以了。

共享标签

git push命令不会将标签传送到远程,可以使用下面的命令显示推送某个标签
git push [remote-name] [tag-name]
如果要推送多个标签,使用:
git push [remote-name] --tags

别名

git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
可以看出,Git 只是简单地将别名替换为对应的命令。 然而,你可能想要执行外部命令,而不是一个 Git 子命令。 如果是那样的话,可以在命令前面加入 ! 符号。 如果你自己要写一些与 Git 仓库协作的工具的话,那会很有用。

分支

暂存操作会为每一个文件计算校验和(使用我们在 起步 中提到的 SHA-1 哈希算法),然后会把当前版本的文件快照保存到 Git 仓库中(Git 使用 blob 对象来保存它们),最终将校验和加入到暂存区域等待提交。
当使用 git commit 进行提交操作时,Git 会先计算每一个子目录(本例中只有项目根目录)的校验和,然后在 Git 仓库中这些校验和保存为树对象。随后,Git 便会创建一个提交对象,它除了包含上面提到的那些信息外,还包含指向这个树对象(项目根目录)的指针。如此一来,Git 就可以在需要的时候重现此次保存的快照。
看图

image

在一次提交后,包含3类文件,提交对象commit,目录的树对象tree,文件的blob对象。tree和blob是git对当前文件状态的一次快照snapshot。因此,每次提交产生的commit指向了一次snapshot。
在多次提交后,后来提交的commit对象会指向上一次提交的父对象。分支就是一个指针,指向某次提交,另外git中还有一个默认的指针,HEAD,指向当前分支。关系如下:
image

当使用 git checkout bname后,HEAD指针就指向bname了。

分支切换会改变你工作目录中的文件

在切换分支时,一定要注意你工作目录里的文件会被改变。 如果是切换到一个较旧的分支,你的工作目录会恢复到该分支最后一次提交时的样子。 如果 Git 不能干净利落地完成这个任务,它将禁止切换分支。
git log --oneline --decorate --graph --all输出你的提交历史、各个分支的指向以及项目的分支分叉情况。

git branch

  • git branch bname: 创建分支bname
  • git branch 列出所有分支,星号表示当前所在分支
  • git checkout bname: 切换到bname分支
  • git merge bname : 将bname合并到当前分支(可能是主分支)。如果存在矛盾(conflict),git会提示。使用git diff可以看到,编辑矛盾的文件(矛盾的地方会标记出来),然后git commit -a即可完成merge.
  • gitk,可以以图形形式查看
  • git branch -d bname: 删除bname分支。

远程分支

远程跟踪分支是远程分支状态的引用。 它们是你不能移动的本地引用,当你做任何网络通信操作时,它们会自动移动。 远程跟踪分支像是你上次连接到远程仓库时,那些分支所处状态的书签。
它们以 (remote)/(branch) 形式命名。,本地无法修改,一般在进行网络操作时自动修改。
像下图这样

image

本地的master和远程的master分支不同,如果要将本地master推送到远程是不行的,需要首先进行合并:
首先抓取git fetch origin
然后合并git merge origin\master
然后将master分支推送上去git push origin master
具体参见第5部分,分布式git。

git clone

  • git clone remote local: 将repository remote 克隆到 local。local克隆的是remote的当前分支,即如果remote处于branch状态,那么local克隆的也是branch状态,并且不包含主分支。
  • 当在local上完成改动并commit之后,需要请求remote一方pull local一方的改动。
    git pull local master: 完成了两个动作,首先把local中的master 分支fetch到了,然后将改动merge到当前branch中。
  • 在执行pull之前,要将当前branch的内容commit。
  • 一个更保险的做法是先手动fetch,比较一下不同再决定是否merge(可以再pull一下或者merge:git merge FETCH_HEAD)。使用下面的命令:
    git fetch local,fetch得到的节点会以FETCH_HEAD标记。
    git log -p HEAD..FETCH_HEAD: 其中"HEAD..FETCH_HEAD" means "show everything that is reachable from the FETCH_HEAD but exclude anything that is reachable from HEAD"显示只有FETCH_HEAD有而HEAD没有的内容。
    也可以使用HEAD...FETCH_HEAD标记,表示show everything that is reachable from either one, but exclude anything that is reachable from both of them,只显示差异不显示相同的。
    以上命令都可以使用gitk进行图形查看。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • Git 基础 基本原理 客户端并不是只提取最新版本的文件快照,而是把代码仓库完整的镜像下来。这样一来,任何一处协同...
    __silhouette阅读 15,860评论 5 147
  • Git 命令行学习笔记 Git 基础 基本原理 客户端并不是只提取最新版本的文件快照,而是把代码仓库完整的镜像下来...
    sunnyghx阅读 3,907评论 0 11
  • 昨天晚上出去遛弯,感觉水面虽然结冰,应该不太厚,竟然有人在冰面上,看着像钓鱼。抛开安全,这种生活蛮有意思的。 朋友...
    杨继彬阅读 142评论 0 0
  • 其实人一旦长大,就不再是完成一个阶段就能静下来或是疯狂的撒野一段时间,就比如小学毕业,中考结束,大学的开始。都曾经...
    Memememe阅读 203评论 0 0
  • 你是否感曾经到不自由?你是否在某些情况下退而求其次?你是否还有没有实现的梦想。你觉得自己渴望改变,但又无法...
    g大师阅读 125评论 0 2