Pro Git 学习笔记

学习 Pro Git 一书的学习笔记。
采用教材:Pro Git 中文版

一、起步

关于版本控制

  • 本地版本的控制 rcs 保存并管理文件补丁(patch)
  • 集中化的版本控制系统 CVS SubVersion Perfoce, 有集中的服务器管理版本,本地每次获得最新版本代码。
  • 分布式版本控制系统

Git 历史

2005年一直免费试用的 分布式版本控制系统 BitKeeper 的商业公司停止了对 Linux 的免费授权, Linus 就带领社区撸了一个分布式版本管理系统。

git 基础概念

  • 文件快照,直接保存文件,而不是差异比较
  • 本地操作 可以不用连接网络仓库 疯狂提交代码
  • 时刻保证数据完整性

文件的三个状态

  • 已提交
  • 已修改
  • 已暂存

git 安装和配置

安装

源码安装,或者编译包安装。

配置:

配置和查看 git 环境:

git config 实际上调用的是 git-config 命令,但是至今输入git-config 找不到这个命令

git config —sytem 配置系统环境 系统所有用户通用的配置
git config —global 配置当前用户环境 在 ~/.gitconfig 目录下配置。
git config 设置当前项目的配置 在.git/config目录下记录

git config —list 查看所有配置信息

获得帮助信息。

git help config
git config –help
man git-config

二、Git 基础

git init 初始化仓库

git add *.java
git add README
git commit -m “first commit”

克隆现有的项目

git clone [本地名称]

检查当前文件状态。
git status

有没有跟踪的文件 或者有修改 的文件会在这里显示。

$ vim README
$ git status
On branch master
Untracked files:
(use “git add …” to include in what will be committed)

README

nothing added to commit but untracked files present (use “git add” to track)

同样 如果仓库clean 也会显示出来。

$ git status
On branch master
nothing to commit, working directory clean

跟踪新文件

git add README

再次执行 git status

1
2
3
4
5
6
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

new file: README

git add 添加文件到暂存区

暂存已修改的文件 已经改被跟踪的文件 再次修改,

添加到缓存区后 ,再次修改, 会看到两个该文件显示出来

$ vim benchmarks.rb
$ git status
On branch master
Changes to be committed:
(use “git reset HEAD …” to unstage)

new file:   README
modified:   benchmarks.rb

Changes not staged for commit:
(use “git add …” to update what will be committed)
(use “git checkout – …” to discard changes in working directory)

modified:   benchmarks.rb

顺便学习到的 命令

废弃本次修改
(use “git checkout – …” to discard changes in working directory)

从缓冲区中撤回
(use “git reset HEAD …” to unstage)

忽略部分文件。

编译好的的文件,日志文件, 编辑器生成的临时备份文件 等等不需要上传到代码仓库
可以在 .gitignore 文件中配置忽略文件
最好一开始就变就好,免得不需要的文件被提交。

gitignore文件规则:

  • 空行或者# 开头的会被git忽略。
  • 可以使用标准的 glob 模式匹配。
  • 匹配模式最后跟反斜杠(/)说明要忽略的是目录。
  • 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。

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

我们再看一个 .gitignore 文件的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 此为注释 – 将被 Git 忽略
# 忽略所有 .a 结尾的文件
*.a
# 但 lib.a 除外
!lib.a
# 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
/TODO
# 忽略 build/ 目录下的所有文件
build/
# 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
doc/*.txt
# ignore all .txt files in the doc/ directory
doc/**/*.txt

A **/ pattern is available in Git since version 1.8.2.

采用
git commit 提交。

加上-v可以显示更多的详细的改变信息。
git commit -v

处理的文本编辑器 # 开头的会被好忽略,首行空着用来输入提交记录。

也可以用过 git commit -m “提交说明” 的方式直接提交。

加上 -a 参数可以跳过 git add的步骤。

如果文件都是一件被 add 过的话

git commit -a -m “不用 git add 的提交。 “

移除文件

本地磁盘删除文件
rm filename
查看 git status
得到 Changes not staged for commit:

$ git status
On branch master
Changes not staged for commit:
(use “git add/rm …” to update what will be committed)
(use “git checkout – …” to discard changes in working directory)

deleted:    grit.gemspec

no changes added to commit (use “git add” and/or “git commit -a”)

所以需要在git 中移除文件
git rm finame

加上 -f f是 force的缩写,可以删除 修改过并且已经放到暂存区域的文件。

从暂存区删除 ,但是本地仓库保留。

这个适用于不小心把一个写大的文件加入到了仓库跟踪中,可以用这样的办法仅仅去掉跟踪。

git rm –cached video.mp4

移动文件

git mv file_from file_to

1
TODO 实验,名字从小写改成大写。    之前的操作似乎是不敏感的, 尝试用  git mv 操作。

查看提交历史

git log
不加参数看全部的提交记录,

git log -p 附带每次提交的差异比较
-2 表示查看最近2条记录。

–word-diff 单词层面的比较。

得到结果:

会有如下: git [-init-]{+in0t+}

[- -]中的是删除的单词, {+ +} 中是新插入的单词。

加上 -U1 可以让上下文的行数从 默认3行变为1行。

其他的参数

–stat,仅显示简要的增改行数统计
–pretty 稍微简约一些的展示方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
commit d2af3ae2b9e7b08f5f734ce81ac0cee21e4a7c38
Author: JerryZhang <jerry0908mo@163.com>
Date: Mon Jun 20 16:48:14 2016 +0800

test 2nd word diff

commit fec4ad1f0184ebca0cd01097bc3ec7785a91c99e
Author: JerryZhang <jerry0908mo@163.com>
Date: Mon Jun 20 16:46:35 2016 +0800

test word diff

commit bf7b1fb2a5946a60f057303b0854f587a0ae527c
Author: JerryZhang <jerry0908mo@163.com>
Date: Wed Jun 15 00:57:50 2016 +0800

不用git add直接 commit

commit a9b128c3820b4804aa330772bc81c4b84d24132c
Author: JerryZhang <jerry0908mo@163.com>
Date: Wed Jun 15 00:51:26 2016 +0800

添加gitigonre文件
readme书写了简单笔记。

–oneline 每个提交展示在一行

1
2
3
4
d2af3ae test 2nd word diff
fec4ad1 test word diff
bf7b1fb 不用git add直接 commit
a9b128c 添加gitigonre文件 readme书写了简单笔记。

–graph 简单的图形化展示 展示演变

1
git log --pretty=oneline

format 可以指定显示格式 方便写程序提取分析

1
2
3
4
$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 11 months ago : changed the version number
085bb3b - Scott Chacon, 11 months ago : removed unnecessary test code
a11bef0 - Scott Chacon, 11 months ago : first commit

搜索提交记录查看日志

git log –grep=”题型”

git log –grep=”题型” –grep=”商务” –all-match
同时满足两个条件 需要加上–all-match

查看指定目录或者文件的历史记录
git log – build.gradle

–author=JerryZhang 指定作者 查看提交记录

图形化工具 gitk 查看。

撤销操作

提交后发现,少了几个文件,或者提交信息写错了,可以撤销重新提交

直接修改提交信息:git commit –amend
忘记文件:直接添加文件后,输入 git commit –amend

1
2
3
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend

取消已经暂存的文件,这个在git status 查看的时候就有提醒。

git reest HEAD filename

取消对文件的修改, 这个在 git status查看时也有提醒。

git checkout – filename

远程仓库的使用

clone 的仓库执行 git remote 后至少可以看到一名为 origin (默认远程库名)的远程仓库。

git remote -v
可以显示对于的克隆地址

1
2
3
➜  ProGitBlog git:(master) git remote -v
origin git@git.coding.net:jerrysher/Blog.git (fetch)
origin git@git.coding.net:jerrysher/Blog.git (push)

如果有多个远程仓库,此时会全部列出

1
2
3
4
5
6
$ git remote -v
bakkdoor git://github.com/bakkdoor/grit.git
cho45 git://github.com/cho45/grit.git
defunkt git://github.com/defunkt/grit.git
koke git://github.com/koke/grit.git
origin git@github.com:mojombo/grit.git

添加远程仓库

git remote add [shortname] [url]:

$ git remote add pb git://github.com/paulboone/ticgit.git
$ git remote -v
origin git://github.com/schacon/ticgit.git
pb git://github.com/paulboone/ticgit.git

可以用 pb 指代 paulboone 用户的 ticgit 仓库了。

从远程仓库抓取信息。

git fetch 可以抓取本地没有 远程有的信息。

git fetch pb

抓取后可以看到所有 pb 远程的所有信息。

git fetch 只抓取数据 没有合并。

git pull 抓取数据并且合并到当前的工作分支

git push [remote-name] [branch-name]
推送数据到远程分支 , 默认是 orgin仓库, master分支

查看远端仓库信息
git remote show origin

1
2
3
4
5
6
7
8
9
10
11
12
➜  ProGitBlog git:(master) git remote show origin
* remote origin
Fetch URL: git@git.coding.net:jerrysher/Blog.git
Push URL: git@git.coding.net:jerrysher/Blog.git
HEAD branch: master
Remote branches:
coding-pages tracked
master tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (fast-forwardable)

列出了所有跟踪中的远端分支,
Local ref configured for ‘git push’: 默认的push 分支,
Local branch configured for ‘git pull’: pull自动合并的分支
Stale tracking branches (use ‘git remote prune’) 本地被跟踪,但是远端已经删除的分支
New remote branches (next fetch will store in remotes/origin) 远程有,还没同步的本地的分支

远程仓库的删除和重命名

git remote rename 修改仓库的简称
git remote rename pb paul pb 改为 paul

移除
$ git remote rm paul

打标签

发布某个版本,打一个标签。

列出所有标签
git tag

可以加上约束条件,列出符合条件的tag (只列出2.2相关的tag)
➜ platform git:(feature/3.1.0(Iron_Man)) ✗ git tag -l ‘2.2*’
2.2.0
2.2.1
2.2.2
2.2.3
2.2.4

新建标签

分两种:轻量级的(lightweight)和 含附注的(annotated)
轻量级,仅仅是一个提交对象引用;含附注的可以带有信息, 有自己的说明,邮箱,标签名字

一般都是含附注的

创建一个tag :
git tag -a v1.4 -m “my version 1.4”

git show [tagname]
查看标签信息,

1
2
3
4
5
6
7
8
9
10
tag v0.1
Tagger: JerryZhang <jerry0908mo@163.com>
Date: Tue Jun 21 00:05:23 2016 +0800

my version 0.1

commit f52eb62eefd38f423864fa2ff6c1cb52dadb91ed
Author: JerryZhang <jerry0908mo@163.com>
Date: Mon Jun 20 16:48:14 2016 +0800
……提交记录信息……

签署标签

如果你有自己的私钥,还可以用 GPG 来签署标签. -s signed的首字母
$ git tag -s v1.5 -m ‘my signed 1.5 tag’

1
2
3
4
5
todo 执行失败 不明白做什么用的
➜ ProGitBlog git:(master) git tag -s v0.2 -m "my version signed 0.2"
error: cannot run gpg: No such file or directory
error: could not run gpg.
error: unable to sign the tag

轻量级标签

git tag v1.4-lw
直接创建 不加参数。

验证标签
可以使用 git tag -v [tag-name] (译注:取 verify 的首字母)的方式验证已经签署的标签。此命令会调用 GPG 来验证签名,所以你需要有签署者的公钥,存放在 keyring 中,才能验证:

$ git tag -v v1.4.2.1

从某次提交创建标签

$ git tag -a v1.2 9fceb02

后面跟上这次提交对象的校验和(或前几位字符就可以)

分享标签。
标签推到远端仓库

git push origin [tagname]

一次性推送所有tag到远端

$ git push origin –tags

1
2
3
4
5
6
7
8
9
➜  ProGitBlog git:(master) git push origin --tags
Warning: Permanently added the RSA host key for IP address '59.56.27.71' to the list of known hosts.
Counting objects: 15, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (14/14), done.
Writing objects: 100% (15/15), 1.95 KiB | 0 bytes/s, done.
Total 15 (delta 3), reused 0 (delta 0)
To git@git.coding.net:jerrysher/Blog.git
* [new tag] v0.1 -> v0.1

其他人克隆后也可以看到这些标签

技巧和窍门

自动补全:
git源代码中的contrib/completion/git-completion.bash文件
改名字(加上点后)。
cp git-completion.bash ~/.git-completion.bash

配置到自己的环境变量文件中:
source ~/.git-completion.bash

两次tab可以不全命令或者参数

别名:

1
2
3
4
5
6
$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status
$ git config --global alias.unstage 'reset HEAD --'
$ git config --global alias.last 'log -1 HEAD'

别名启用外部命令:
自己写了写脚本,加上! 就可以执行
设置用 git visual 启动 gitk:
$ git config –global alias.visual ‘!gitk’

第三章:Git 分支模型

几乎都支持分支,分支可以让你离开主线工作,做其他事情,然后再回来,这个过程大多很昂贵。
Git 切换分支快速,方便。有人把 Git 的分支模型称为“必杀技特性”

何谓分支

分支的新建与合并

分支的管理

利用分支进行开发的工作流程

远程分支

分支的衍合

小结

JerrySher wechat
欢迎关注『程序员在读书』
坚持原创技术分享,您的支持将鼓励我继续创作!