* 1 起步
**  关于版本控制
*** 什么是版本控制?
记录文件变化,查阅特定版本,回溯到之前的状态。任何类型的文件进行版本控制。
复制整个目录 加上备份时间 简单 混淆 无法恢复
本地版本控制 数据库记录历次差异更新
rcs 保存并管理文件补丁(对应文件修订前后的内容变化) 不断打补丁
 
*** 集中化的版本控制系统
不同系统上的开发者协同工作 单一的集中管理的服务器,保存所有的修订版本
。协同人员通过客户端连到这台服务器,取出最新文件或者提交更新。

一定程度上看到项目中的其他人在做什么,掌控开发者的权限,只需管理维护一
个服务器。缺点是服务器的单点故障,宕机 ,磁盘故障,备份不及时,丢失历史更改数据。

*** 分布式版本控制系统
客户端不只提取最新版本的文件快照,而是把代码仓库完整的镜像下来。协同工
作用的服务器发生故障,任何一个镜像出来的本地仓库修复。提取操作,是对代码仓库的完整备份。
和不同的远端代码仓库进行交互。

**  简史
linux内核 bitkeeper 开发属于自己的版本控制
速度 简单设计 对非线性开发模式强力支持 完全分布式 超大规模(速度和数据量)

**  git 基础
*** 直接记录快照,而非差异比较
git只关心数据的整体是否发生变化,不关心文件内容的具体差异,不保存差异
数据,快照那些变化的文件。记录在一个文件系统中。每次提交更新时,遍历文件的
指纹信息,并对文件做一个快照,保存一个指向这次快照的索引。文件没有变化,对上次保存的快照做一链接。

*** 近乎所以操作都是本地执行
绝大部分操作只访问本地的文件和资源,不用联网。
离线频繁提交更新,有网络的时候再上传到远程仓库。

*** 时刻保持数据的完整性
保存到git前,所有数据都要进行内容的校验和计算,并将此结果作为数据的唯
一标识和索引。建在整体架构的最底层,文件传输,或磁盘损坏导致数据缺失,
git会立即察觉。使用SHA-1算法计算数据的校验和,对文件内容和目录结构计算
出SHA-1哈希值,作为指纹字符窜。40个16进制字符

*** 多数操作仅添加数据
常用的git操作是把数据添加到数据库。不可逆的操作,使回退和重现历史版本变得困难。

*** 文件的三种状态
已提交
  文件被安全的保存在本地数据库中

已修改
  修改了某个文件,但还没有提交保存

已暂存
  把已修改的文件放在下次提交时要保存的清单中

git管理项目时,文件流转的三个工作区域:

git目录(本地仓库)
   git clone时的.git目录;
   git clone --bare时,新建的目录本身就是git目录
   用于保存元数据和对象数据库的地方
   克隆镜像仓库时,实际拷贝的就是这个目录的数据

git的工作区
   从项目中取出某个版本的所有文件和目录,用以开始后续工作。
   这些文件从git目录中的压缩对象数据库中提取出来,对工作目录中对这些文件进行编辑

暂存区
   只是一个文件,放在git目录中。

*** git的工作流程
工作目录中修改某些文件
对修改后的文件进行快照,然后保存到暂存区
提交更新,将保存在暂存区中的文件快照永久转存到git目录中

从文件所处的位置来判断状态

** 安装git
***
源码安装;为特定平台预编译好的安装包
源码安装,最新的版本,尝试改进用户体验

*** debian源码编译git
*** ubuntu 12.04 ppa安装git
*** ubuntu 12.04 源码安装git

git的源码使用git clone 获取。先安装git,下载源码
$ sudo apt-get install git

获取编译git的依赖
$ sudo apt-get build-dep git

下载git源码
$ git clone git://git.kernel.org/pub/scm/git/git/git.git git
$ cd git
$ make
$ sudo make install

*** ubuntu 安装预编译好的二进制安装包
$ sudo apt-get install git -y

*** windows 上安装
msysgit
下载地址:http://msysgit.github.com/
安装之后,可以使用命令行的git工具,自带ssh客户端。
还有图形化的git项目管理工具--乌龟  (tortoisegit)

** 初次运行git前的配置
***
配置自己的git工作环境,只需配置一次,以后升级时,会沿用现在的配置。可
以使用相同的命令修改已有的配置。

git config , 用来配置读取相应的工作环境变量。

环境变量可以放在三个不同的地方:
 
/etc/gitconfig
  git config --system ,系统中所有用户适用

~/.gitconfig
  git config --global ,用户目录下的配置文件,只适用于该用户

当前项目的git目录中的配置文件(也就是工作目录中的.git/config文件)
   只针对当前项目有效

每一个级别的配置会覆盖上层的相同配置

*** 用户信息
个人的用户名和电子邮件地址
git提交时,会引用这两条信息,说明是谁提交了更新,随更新内容一起永久纳入历史记录

$ git config --global user.name "vipzrx"
$ git config --global user.email "vipzrx@gmail.com"

*** 文本编辑器
默认使用的文本编辑器,输入一些额外的消息。
$ git config --global core.editor emacs

使用emacsclient

*** 差异分析工具
解决合并冲突时,使用那种差异分析工具,合并工具。

使用ediff

*** 查看配置信息
检查已有的配置信息

$ git config --list
user.name=vipzrx
user.email=vipzrx@gmail.com
core.editor=emacsclient
diff.tool=ediff
diff.guitool=ediff
difftool.ediff.cmd=~/.emacs.d/shell/ediff.sh $LOCAL $REMOTE $MERGED
merge.tool=ediff
mergetool.ediff.cmd=~/.emacs.d/shell/ediff.sh $LOCAL $REMOTE $MERGED $BASE
mergetool.ediff.trustexitcode=true

有时会看到重复的变量名,说明他们来自不同的配置文件,git最终采用的是最后一个。

可以直接检阅某个环境变量的设定,只要把特定的名字跟在后面即可

$ git config user.name
vipzrx

** 获取帮助
阅读工具的使用帮助
$ git help <verb>
$ git <verb> --help
$ man git-<verb>

** irc
#git
#github
irc.freenode.net

* git 基础
**
初始化一个代码仓库
适当配置
开始或者停止追踪某些文件
暂存或者提交某些更新
git忽略某些文件,或者名称符合特定模式的文件
撤销犯下的小错误
浏览项目的更新历史
查看两次更新之间的差异
从远程仓库拉数据下来
推数据到远程仓库

** 取得项目的git仓库
*** 两种方法:
1 在现存的目录下,通过导入所有文件来创建新的git仓库
2 从已有的git仓库克隆出一个新的镜像仓库

*** 在工作目录中初始化新仓库

对现有的某个目录开始用git管理,只需在此项目所在的目录,执行:
$ git init

初始化后,在当前目录下会出现一个名为.git的目录。所有git需要的数据和资
源都存放在这个目录中。仅是按照既有的结构框架初始化好了里面所有的文件和
目录,还没有开始追踪管理项目中的任何一个文件。

当前目录下的文件想要纳入版本控制,需要先使用 git add ,告诉git 开始对
这些文件进行跟踪,然后提交
$ git add *.c
$ git add README
$ git commit -m "XXXX"

*** 从现有仓库克隆
为开源项目出力,先把该项目的git仓库复制一份出来,使用git clone

git获取的是项目历史的所有数据(每一个文件的每一个版本),服务器上有的数据克隆
之后本地也有了。服务器磁盘发生故障,用任何一个克隆出来的客户端可以重建服务器上的仓库,可能会损失服务器端的挂钩设置。

克隆仓库的命令是: git clone [git://XXXXX-XXX.git] <DIR>/<dir>

会在<DIR>创建<dir>目录,其中包含一个.git目录,用于保存下载下来的所有版本记录,
然后从中取出最新版本的文件拷贝。

git支持多种协议,
git://
http(s)://
ssh协议 user@server:/path.git

*** 记录每次更新到仓库

有了项目的git仓库,并从这个仓库中取出所有文件的工作拷贝。对这些文件修
改,完成一个阶段的目标后,提交本次更新到仓库。

工作目录下的文件不外乎两种状态: 已跟踪或未跟踪

已跟踪:本来就纳入版控的文件,上次快照中有他们的记录,工作一段时间后,
他们的状态可能是未更新,已修改或者已经放入暂存区。

未跟踪:既没有上次更新时的快照,也不在当前的暂存区域。

初次克隆某个仓库时,工作目录中的所有文件都属于已跟踪,且状态为未修改。
 
在编辑过某些文件之后,git将这些文件标记为已修改。逐步把修改过的文件放
到暂存区,直到最后一次性提交所有这些暂存起来的文件。

*** 检查当前文件的状态
确定哪些文件处于什么状态,使用 git status
未跟踪的文件意味着git在之前的快照(提交)中没有这些文件,git不会自动将之纳入跟踪范围,除非使用git add

*** 跟踪新的文件
开始跟踪一个新的文件,使用 git add
$  touch README

$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#    README
nothing added to commit but untracked files present (use "git add" to track)

$ git add README

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#    new file:   README
#
文件README已经被跟踪,并处于暂存状态

在# Changes to be committed: 这行下面的,就说明是已暂存状态。

git add 后面可以指明要跟踪的文件或者目录路径。如果是目录,递归跟踪目录下的所有文件。
git add 是将目标文件,已跟踪的,快照放入暂存区;未跟踪过的文件标记为需要跟踪,并放入暂存区

*** 暂存已修改的文件

修改README
$ echo 123 >>README

修改之后的status
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#    new file:   README
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#    modified:   README
#

README文件出现了两次,一次算未暂存,一次算已暂存。 实际上git 只是暂存了运行git add时的版本,如果现在提交,提交的是git add时的版本,不是git add之后修改过的版本。

在运行了git add 之后又做了修改的文件,需要重新运行git add把最新的版本暂存起来。

$ git add README
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#    new file:   README

***  忽略某些文件

有些文件无需纳入git的管理,也不希望他们总出现在未跟踪文件列表中。
通常是自动生成的文件,如日志文件,编译过程中创建的临时文件。
可以创建一个名为.gitignore的文件。列出要忽略的文件模式

.gitignore的格式规范:
所有空行或者以注释符号#开头的行都会被git忽略
可以使用标准的glob模式匹配
匹配模式最后跟返斜杠(/)说明要忽略的是目录
要忽略指定模式以外的文件和目录,可以在模式前加上惊叹号(!)取反

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

*** 查看已暂存和未暂存的更新
git status 仅显示修改过的文件。
要查看具体修改了什么地方,可以用git diff
 查看尚未暂存的文件更新可哪些部分 git diff
git diff 比较的是工作目录中当前文件和暂存区快照之间的差异,也就是修改之后还没有暂存起来的变化内容
要查看已经暂存起来的文件和上次提交时的快照之间的差异,可以使用 git diff --cached ,git 1.6 版本之后可以用 $ git diff --staged

修改benchmarks.rb后不暂存
$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#    modified:   README
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#    modified:   benchmarks.rb
#

$ git diff
diff --git a/benchmarks.rb b/benchmarks.rb
index e69de29..a8a0be4 100644
--- a/benchmarks.rb
+++ b/benchmarks.rb
@@ -0,0 +1,2 @@
+123
+1233456

使用git diff --cached 查看已经暂存起来的变化

$  git diff --cached
diff --git a/README b/README
index 190a180..b4ee7ef 100644
--- a/README
+++ b/README
@@ -1 +1,2 @@
 123
+12345

*** 提交更新
暂存区准备好之后,就可以提交了。
在提交之前,要确定修改过的或是新建的文件有没有git add过,否则提交的时候不会记录这些还没有暂存起来的变化。
每次提交前,先用git status 看下是不是都已暂存起来了,然后运行提交命令:git commit

$ git commit 这种方式会启动文本编辑器,输入本次提交的说明。

使用git config --global core.editor设定使用的编辑器

默认的提交信息包含最后一次运行 git status 的输出,放在注释行里。

开头有一空行,以供输入提交说明。

使用-v ,将修改差异的每一行都包含到注释中来。

退出编辑器,git会丢掉注释行,将说明内容和本次更新提交到仓库。

不填写提交说明,不能进行提交;提示信息如下:
Aborting commit due to empty commit message.

也可以使用-m 参数后跟提交说明的方式,在一行命令中提交更新:

$ git commit -m "提交的更新说明"

$ git commit -v
Waiting for Emacs...
[master ad44b9c] dsafas
 1 file changed, 1 insertion(+)

提交后的输出信息,可以看到 ,当前是在哪个分支(master)提交,本次提交的完整SHA-1校验和是ad44b9c,以及在本次提交中,有
一个文件修订过,1行增加

提交时记录的是放在暂存区中的快照,任何还未暂存的仍然保持已修改状态,可以在下次提交时纳入版控。
每次提交操作,都是对你项目的一次快照,以后可以回到这个状态,或者比较。

*** 跳过使用暂存区
使用暂存区的方式可以精心准备要提交的细节,有时显得繁琐。

git提供一个跳过暂存区的方式,使用git commit -a ,git会自动把所有已经跟踪过的文件暂存起
来一并提交,从而跳过暂存区

*** 移除文件

从git中移除文件,需从已跟踪文件清单中清除(确切说,暂存区),然后提交。

用git rm ,从已跟踪清单中删除文件,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪
文件清单中了,当前工作目录中的文件也被删除了,该文件不再纳入版控管理了。

$ git rm README
rm 'README'

$ ls README
ls: cannot access README: No such file or directory

$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 2 commits.
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#    deleted:    README

$ git commit -m "delete README"
master 1206d93] delete README
 1 file changed, 2 deletions(-)
 delete mode 100644 README

Changes not staged for commit: 是未暂存清单

Changes to be committed:对于已跟踪文件是暂存清单;对于未暂存文件,是已跟踪清单和暂存清单

如果只是简单的从工作目录中手工清除文件,运行git status 会在未暂存清单看到

如果删除前,修改过并且已经放到暂存区,但还没有提交,使用-f 。

想把文件从git仓库中删除(从暂存区移除),但仍然希望保留在当前工作目录中。即仅从跟踪清单中删除,但不删除文件,以便在.gitignore文件补上,用--cached

$ git rm --cached README

后面可以列出文件或者目录的名字,也可以使用glob模式

$ git rm log/\*.log
git有自己的文件模式匹配方式

$ git rm \*~
递归删除当前目录及其子目录中所有~结尾的文件

*** 移动文件
git不跟踪文件的移动。在git中重命名了某个文件,仓库中存储的元数据不会体现出这是一次改名操作。不过git能够推断出究竟发生了什么。
$ git mv file_from file_to

运行git mv 相当于下面三条命令:
$ mv file_from file_to
$ git rm file_from
$ git add file_to

如此分开操作,git也会意识到这是一次改名操作。
直接用git mv 轻便;有时用其他工具批量改名的话,记得在提交前删除老的文件,再添加新的文件名

** 查看提交历史
提交了若干更新,或者克隆了某个项目,想回顾一下提交历史,用git log
默认不用任何参数,git log 会按照提交时间列出所有的更新,最近的更新排在最上面。
每次更新都有一个SHA-1校验和、 作者的名字和邮箱、提交时间、最后缩进一个段落显示提交的说明

常用的选项:
-p 展开显示每次提交的内容差异
-2 仅显示最近的两次更新

--stat 仅显示简要的增改行数统计
每个提交都列出了修改过的文件,以及其中添加和移除的行数,并在最后列出所有增减数小计

--pretty 指定完全不同于默认格式的方式展示提交历史
--pretty=oneline 将每个提交放在一行显示,在提交数很大的时候有用
--pretty=format: 可以定制显示的记录格式,这样的输出便于后期分析
常用的格式占位符及其代表的意义

作者和提交者的差别
作者指的是实际作出修改的人,提交者是最后将此工作成功提交到仓库的人

用oneline 或format时,结合--graph选项,可以看到开头多出一些ASCII字符串表示的简单图形,形象的展示了每个提交所在的分支及其分化衍合情况

*** 限制输出长度
除了定制输出格式的选项,git log 还有限制输出长度的选项,也就是只输出部分提交信息。
按时间做限制的选项

--since
--until
$ git log --since=2.weeks
可以给出各种时间格式 :具体的某一天 或者多久以前
还可以给出若干搜索条件,列出符合的提交
用--author 指定提交的作者
用--grep搜索提交说明中的关键字
要得到同时满足这两个选项搜索条件的提交,必须用--all-match .否则,满足任意一个条件的提交都会被匹配出来

如果只关心某些文件或者目录的历史提交。可以在git log选项的最后指定他们的路径。因为是放在最后位置上的选项,所以用两个短划线--隔开之前的选项和后面限定的路径名
$ git log  -- <path>
$ git log  -- ./111

*** 使用图形化工具检阅提交历史
图形化工具更容易展示历史提交的变化。
使用tcl/tk写成, 是git log的可视化版本,凡是git log 可以用的选项也都可以用在gitk上

安装
$ sudo apt-get install gitk

启动
$ gitk

** 撤销操作
***
任何时候 ,都有可能撤销刚才所做的某些操作。有些操作是不可逆的

*** 修改最后一次的提交

提交完了发现漏掉了几个文件没有追加,或者提交信息写错了。想要撤销刚才
 的提交操作,可以使用--amend

$ git commit --amend

此命令将使用当前的暂存区快照提交。如果刚才提交完,没有做任何改动,直接
运行此命令,相当于重新编写提交说明,将要提交的文件和之前的一样

启动文本编辑器之后,会看到上次提交的说明,编辑它后确定没有问题后保存,
退出,就会使用新的提交说明覆盖刚才失误的提交。

如果刚才提交时,忘了暂存某些文件,可以先补上暂存操作,然后再运行--amend提交
$ git commit -m "initial commit"
$ git add forgotten_file
$ git commit --amend -m "the correct commit"

上面的三条命令只是产生一个提交,第二个提交命令修正了第一个的提交内容。

*** 取消已经暂存的文件
查看文件状态的时候就提示了该怎么撤销
$ git reset HEAD <file>

*** 取消对文件的更改
抛弃文件修改,恢复到修改前的版本
$ git checkout -- <file>
这个命令很危险,用之前版本的文件复制过来重写了此文件
在使用这条命令前,务必确定真的不需要保留刚才的修改。
如果只是想回退版本,同时保留刚才的修改,以便将来继续工作,可以用stashing和分支来处理

任何提交到git的,都可以恢复。即便在已经删除的分支中的提交,或者用--amend重新改写的提交,都可以恢复。
你可能失去的数据,仅是没有提交过的,对git来说,他们就像从未存在过一样

** 远程仓库的使用
***
参与git项目的协作,需了解如何管理远程仓库。
远程仓库是托管在网络上的项目仓库,可能会有好几个,其中有些你只能读,有些你可以写。

同他人协作开发某个项目,需要管理这些远程仓库,以便推送或拉取数据,分享各自的工作进展。

*** 查看当前的远程仓库
查看当前配置的远程仓库,使用 git remote,他会列出每个远程仓库的简短名
字。在克隆完某个项目之后,至少可以看到一个名为origin的远程仓库,git默
认使用这个名字来标识你所克隆的原始仓库。

git remote -v 显示对应的克隆地址
如果有多个远程仓库,此命令将全部列出

*** 添加远程仓库

添加一个远程仓库 ,可以指定一个简单的名字,以便将来使用。

git remote add [short_name] [url]

可以使用short_name来指代对应的仓库地址。

*** 从远程仓库抓取数据

从远程仓库抓取本地仓库中没有的数据到本地。

运行完之后,就可以在本地访问远程仓库中的所有分支,将其中的分支合并到本
地,或者只是取出某个分支。

$ git fetch [remote_name]

如果是克隆了一个仓库,此命令会自动将远程仓库归于origin名下。所以 git fetch origin

会抓取从你上次克隆以来,别人上传戴此仓库中的所有更新(或是上次fetch以来别人提交的更新)

fetch命令只是将远端的数据拉到本地仓库,并不自动合并到当前工作分支,只
有当你准备好了,才能收定合并

如果设置了某个分支用于跟踪某个远端仓库的分支,可以使用git pull 命令自
动抓取数据下来,然后将远端分支自动合并到本地仓库中当前分支。

*** 推送数据到远程仓库

项目进行到一个阶段,要同别人分享目前的成果,可以将本地仓库中的数据推送到远程仓库。

git push [remote_nmae] [branch_name]

如果要把本地的master分支推送到origin服务器上,使用
$ git push origin master
 
只有在所克隆的服务器上有写权限,而且同一时刻没有其他人在推送数据,这条
命令才会成功。

如果在你推送数据之前,已经有其他人推送了若干更新,你的推送操作会被驳回。
你必须先把他们的更新抓到本地,合并到自己的项目中,然后才可以再次推送。

*** 查看远程仓库的信息
通过git remote show  [remote_name] 查看某个远程仓库的详细信息

$ git remote show origin

* remote origin
  Fetch URL: https://github.com/vipzrx/11.git
  Push  URL: https://github.com/vipzrx/11.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)

*** 远程仓库的删除和重命名
$ git remote rename <old_name> <new_name>

对远程仓库的重命名,也会使对应的分支名称发生变化,原来的
<old_name>/master变成 <new_name>/master

碰到远程仓库服务器迁移,或者原来的克隆镜像不再使用,又或者某个参与者不
再贡献代码,那么就需要移除对应的远端仓库

$ git remote rm <remote_name>

** 打标签
***
git可以对某一时间点上的版本打上标签。人们在发布某个软件版本的时候,经常这样做。

*** 列显已有的标签
$ git tag

显示的标签按照字母顺序排列
可以使用特定的搜索模式列出符合条件的标签

*** 新建标签
git使用的标签有两种:轻量级的和含附注标签
轻量级标签是个不会变化的分支,实际上它是个指向特定提交对象的引用。
含附注的标签是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,邮件地址和日期,以及标签的说明,标签本身允许使用GPG来签署或验证。

一般建议使用含附注的标签,以便保留相关的信息

如果临时加注标签,或者不需要额外信息,用轻量级标签没问题,很方便。

*** 含附注的标签
$ git tag -a <tag-name> -m "tag-commit-description"

-m指定相应的标签说明,git会将此说明一同保存在标签对象中。如果没有给出
该选项,git会启动文本编辑器供你输入标签说明

$ git show 2013-11-28
tag 2013-11-28
Tagger: vipzrx <vipzrx@gmail.com>
Date:   Thu Nov 28 15:52:40 2013 +0800

2013年11月28日

commit ff9b3b04785b2f1635afa37036437c67315038e6
Author: vipzrx <vipzrx@gmail.com>
Date:   Thu Nov 28 11:15:34 2013 +0800

qqq

diff --git a/111 b/111
new file mode 100644
index 0000000..190a180
--- /dev/null
+++ b/111
@@ -0,0 +1 @@
+123

$ git show <tag-name>
显示相应标签的版本信息,并连同显示打标签时的提交对象
提交对象信息上面,列出了此标签的提交者和提交时间,以及相应的标签说明

*** 签署标签
如果你有自己的私钥,可以使用GPG来签署标签
$ git tag -s <tag-name> -m "tag-commit-description"

再次运行git show <tag-name> 会看到对应的GPG签名也附在其中

*** 验证已经签署的签名
$ git tag -v <tag-name>
验证已经签署的标签
此命令会调用GPG来验证签名,所以你需要有签署者的公钥,存放在keyring中,才能验证

*** 后期加注标签
后期对早先的某次提交加注标签
在打标签的时候跟上对应提交对象的校验和(或前几位数字)
$ git tag -a <tag-name> <某次提交对应的校验和>

*** 分享标签
默认情况下,git push不会把标签传送到远端服务器上,只有通过显式命令才能分享标签到远端仓库

$ git push <remote-name> <tag-name>
$ git push origin <tag-name>

如果要一次推送本地所有新增的标签上去,使用
$ git push origin --tags

其他人克隆仓库或拉取数据同步后,也会看到这些标签

*** 轻量级标签
轻量级标签实际上是一个保存着对应提交对象的校验和信息的文件。
$ git tag <tag-name>
使用git show <tag-name>查看此标签,就只有相应的提交对象摘要

** 技巧和窍门
*** 自动补全
apt安装的git 支持自动补全

$ ls /etc/bash_completion.d/ | grep git
git

/etc/bash_completion.d/ 这个目录中的脚本,会在bash启动时自动加载

输入git命令的时候,可以敲两次TAB,就会看到列出所有匹配的可用的命令建议

命令的选项也可以用这样的方式完成

*** git 命令别名

git不会推断你输入的几个字符将会是哪条命令,可以使用git config 为命令设置别名

$ git config --global alias.<别名> <命令>

使用这种技术还可以创造出新的命令

取消暂存文件时的输入比较繁琐
这样设置:
$ git config --global alias.unstage 'reset HEAD'

这样一来,下面的两条命令完全等同
$ git unstage fileA
$ git reset HEAD -- fileA

$ git config --global alias.last 'log -1 HEAD'

查看最后一次的提交信息
$ git last

git的别名只是简单地在命令中替换了你设置的别名。
希望运行某个外部命令,而非git的子命令。只需要在命令前加上!就行
自己写处理git仓库信息的脚本,可以用这种技术包装起来。

设置用git visual启动gitk

$ git config --global alias.visual '!gitk'

*** 小结
git的本地操作:创建和克隆仓库,作出修改,暂存并提交修改,以及查看所有历史修改记录

progit 学习笔记-- 1 第一章 第二章的更多相关文章

  1. 精读《C++ primer》学习笔记(第一至三章)

    第一章: 重要知识点: 类型:一种类型不仅定义了数据元素的内容,还定义了这类数据上可以进行的运算:所以说类定义,实际上就是定义了一种数据类型: >>和<<运算符返回其左侧的运算 ...

  2. Hadoop学习笔记2 - 第一和第二个Map Reduce程序

    转载请标注原链接http://www.cnblogs.com/xczyd/p/8608906.html 在Hdfs学习笔记1 - 使用Java API访问远程hdfs集群中,我们已经可以完成了访问hd ...

  3. 嵌入式学习笔记(综合提高篇 第二章) -- FreeRTOS的移植和应用

    1.1    资料准备和分析 上章节通过实现双机通讯,了解如何设计和实现自定义协议,不过对于嵌入式系统来说,当然不仅仅包含协议,还有其它很多需要深入学习了解的知识,下面将列出我在工作和学习上遇到的嵌入 ...

  4. Stealth视频教程学习笔记(第一章)

    Stealth视频教程学习笔记(第一章) 本文是对Unity官方视频教程Stealth的学习笔记.在此之前,本人整理了Stealth视频的英文字幕,并放到了优酷上.本文将分别对各个视频进行学习总结,提 ...

  5. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十五章:第一人称摄像机和动态索引

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十五章:第一人称摄像机和动态索引 代码工程地址: https://g ...

  6. 20145330《Java学习笔记》第一章课后练习8知识总结以及IDEA初次尝试

    20145330<Java学习笔记>第一章课后练习8知识总结以及IDEA初次尝试 题目: 如果C:\workspace\Hello\src中有Main.java如下: package cc ...

  7. 《python基础教程(第二版)》学习笔记 函数(第6章)

    <python基础教程(第二版)>学习笔记 函数(第6章) 创建函数:def function_name(params):  block  return values 记录函数:def f ...

  8. 《python基础教程(第二版)》学习笔记 字典(第4章)

    <python基础教程(第二版)>学习笔记 字典(第4章)创建字典:d={'key1':'value1','key2':'value2'}lst=[('key1','value1'),(' ...

  9. 《python基础教程(第二版)》学习笔记 字符串(第3章)

    <python基础教程(第二版)>学习笔记 字符串(第3章)所有的基本的序列操作(索引,分片,乘法,判断成员资格,求长度,求最大最小值)对字符串也适用.字符串是不可以改变的:格式化输出字符 ...

随机推荐

  1. 【aspnetcore】模拟中间件处理请求的管道

    几个核心对象: ApplicationBuilder 就是startup->Configure方法的第一个参数,请求(HttpContext) 就是由这个类来处理的 HttpContext 这个 ...

  2. 转 用好HugePage,告别Linux性能故障

    超过32G 的数据库,可以是使用如下方法配置. ######### Slow Performance with High CPU Usage on 64-bit Linux with Large SG ...

  3. JavaMailSender怎么发送163和qq邮件

    https://blog.csdn.net/Tracycater/article/details/73441010 引入Maven依赖包 <dependency> <groupId& ...

  4. 从零开始利用vue-cli搭建简单音乐网站(八)

    这是完成了预想中的最后两个功能:歌曲评论以及歌曲搜索. 1.评论效果: 用户点击评论按钮,评论框获取焦点. 输入之后点击提交,下方显示评论,用户名称以及日期.相应的用户也可以删除自己评论. 当然只能删 ...

  5. Android Studio你必须学会的快捷键(Eclipse转AS必看)

    前言:从Eclipse转到Android Studio之后,一开始把keymap设置成Eclipse,却发现有些常用的快捷键都失效了,大概是冲突了.想了下,觉得与其重新设置快捷键,不如去适应AS的快捷 ...

  6. listView onItemClick失效

    1.先检查list是否设置监听onItemClick事件 2.ListView中有按钮时,会使子项的onItemClick事件无效,如果onItemClick不能触发,在ListView子项目布局文件 ...

  7. 【extjs6学习笔记】0.1 准备:基础概念 (01)

    1. Ext.application 应用程序入口点 2. Ext.onReady() 页面加载完成后触发动作 3. Ext.define() 4. Ext.data.proxy.Proxy 5. E ...

  8. 基于H5+ API手机相册图片压缩上传

    // 母函数 function App(){} /** * 图片压缩,默认同比例压缩 * @param {Object} path * pc端传入的路径可以为相对路径,但是在移动端上必须传入的路径是照 ...

  9. 快速排序的一种Java实现

    快速排序是笔试和面试中很常见的一个考点.快速排序是冒泡排序的升级版,时间复杂度比冒泡排序要小得多.除此之外,快速排序是不稳定的,冒泡排序是稳定的. 1.原理 (1)在数据集之中,选择一个元素作为&qu ...

  10. sqlserver 视图用 case when

    视图用 case when 需要 用如下格式,[需要的列名]= case when...,而表里面的case 不用这样 [isNormal]=CASE WHENdbo.c_bdm_head.I_E_F ...