Git

git简要学习

2018-06-12  本文已影响3人  奇而思

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文件规范为:

所谓的 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 add

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

git commit

移除文件 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

选项 说明
%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

远程分支

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

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

git clone

上一篇 下一篇

猜你喜欢

热点阅读