git核心技术揭秘

11个月前 (02-14) admin git 0评论 已收录 364℃

git

设置

修改用户名

git config --global user.name "User"

必填选项

修改邮箱

git config --global user.email "Email"

必填选项

窗口颜色

git config --global color.ui "always"

选项

auto:自动

always:bash和命令行下均彩色

false:不使用彩色

显示设置

git config --global --list

设置命令别名

示例:git config --global alias.ci "commit"

符号和名称

HEAD

当前分支末梢

^

一个脱字符作用为回溯一个版本

示例:18f822e^表示18f822e之前的版本

注意

Windows中如出现^应加双引号

可以使用多个脱字符

可以混合~使用

*~N

回溯N个版本

示例:18f822e~2

标签和分支的有效名称

可以使用反斜杠/,但是不能以之结尾

可以像组织文件目录结构一样组织标签和分支

可以使用圆点.,但不能置于各段名称的开头

不能使用空格、~、^、:、?、*、[等

不能使用编码小于\040的控制字符和删除键

不能出现双圆点..

创建版本库

1.进入源代码存放目录

2.初始化

git init

创建一个.git目录,存放版本库元数据

暂存

将文件添加到版本库的索引

术语

暂存的变更

stage change

工作目录树中打算提交到版本库的变更

暂存区

staging area

暂存操作更新的git的内部索引

示例:git add index.html

参数

-i

交互添加方式

用来选择要暂存的文件或文件的部分内容

功能

1.status.显示与该方式启动时相同的输出

2.update.添加文件到暂存区

输入要暂存的文件号

文件前显示*表示文件将缓存

回车退出该模式

3.revert.取消已暂存的修改

4.add untracked.暂存还没被git跟踪的文件

5.patch.

可选择单个或多个文件添加到暂存区

回车显示这些文件当前内容与版本库的差异

Stage this hunk?

y:是

n:否

q:退出不暂存

a:添加剩余修改

d:放弃剩余修改

g:选择一个块前往

/:正则查找块

j:未决定状态离开这个块,查看下一个未决定块

J:未决定状态离开这个块,查看下一个块

k:未决定状态离开这个块,查看前一个未决定块

K:未决定状态离开这个块,查看前一个块

s:切分当前块到更小

e:手工编辑当前块

?:帮助

6.diff.

7.quit.

8.help.

-p/--patch

进入patch模式

-u

暂存已纳入git版本控制的文件的修改

提交

提交到本地版本库

示例

先暂存再提交

git add some-file

git commit -m "comments"

提交工作目录树所有修改

git commit -m "comments" -a

指定要提交的文件或文件列表

git commit -m "comments" some-file

参数

-m:本次提交的留言

可接受任意多次留言的输入

不带-m参数,启动编辑器提交留言

环境变量GIT_EDITOR的值
标记: 优先级 1

Git的设置core.editor的值
标记: 优先级 2

环境变量VISUAL的值
标记: 优先级 3

环境变量EDITOR的值
标记: 优先级 4

上述值为空,启动VI
标记: 优先级 5

-v:把要提交内容与版本库版本比较结果添加到编辑器中

-a:提交全部修改过的文件

尚未追踪的文件不会添加

SHA-1

用来跟踪提交的哈希码

提交时显示40位哈希码的前7位

注意

git不会跟踪空目录

解决:在目录里添加一个空文件(文件名任意,习惯使用点号.)

增补提交

git commit -C HEAD -a --amend

-C:告诉git复用指定提交的提交留言

-c:打开编辑器,修改已有留言

HEAD:指定的提交名称

--amend:不在版本库里多新的提交记录

注意

增补提交只能针对最后一个提交

如果想更正几个提交前的某个错误,应先git revert

反转提交

git revert -n <提交名称>

-n:告诉git先不提交,可运行多次,最后一次性提交

--no-edit:直接使用默认的提交留言

复位

复位版本库到一个特定版本,之后修改放入工作目录树

git reset <提交名称>

默认为HEAD

可以使用^和~

--soft:暂存所有因复位带来的差异,但不提交

--hard:从版本库和工作目录树中同时删除提交

不可恢复

谨慎使用

分支

创建时机

试验性更改

增加新功能

bug修复

创建

git branch <新分支名> <父分支名/标签名>

git branch <新分支名>

以当前分支为父分支

显示版本库分支

git branch

本地

git branch -r

远程

git branch -a

所有

*绿色字位当前检出分支

切换(检出)分支

git checkout <分支名>

创建并检出分支

git checkout -b <新分支名> <父分支名>

删除分支

注意

从标签到版本树起点的提交记录均在,此时删除分支只是删除分支名字

只有当要删除的分支已经成功合并到当前分支,删除分支操作才会成功

git branch -d <分支名>

git branch -D <分支名>

强制删除

压合合并和拣选合并必须用-D

创建同名新分支,覆盖已有分支

git branch -f <已存在的分支> [<start point>]

分支重命名

git branch -m <原名> <新名>

不会覆盖已有分支名称

git branch -M <原名> <新名>

如果分支名已存在,强制覆盖现有分支

合并分支间的修改

直接合并(straight merge)

把两条分支上的历史轨迹合并

git merge <想合并到当前分支的源分支名>

--no-commit:合并但不提交

压合合并(squadhed commits)

把一条分支上的若干提交条目压合成一个提交条目,提交到当前分支末梢

git merge --squash <要提交压合的分支>

注意

merge后并未提交,需要提交

拣选合并(cherry-picking)

拣选另一条分支上的某个提交条目的改动到当前分支

git cherry-pick <提交的7位hash码>

拣选多个提交

git cherry-pick -n <提交的7位hash码>

可多次执行该语句,直至完成

最后git commit提交,不加-m

冲突处理

简单合并

手工修改

复杂合并

Linux、Windows:kdiff3

OS X:opendiff

git mergetool

启动一个合并工具

查看本地git设置中的merge.tool的值

可以是kdiff3、tkdiff、meld、xxdiff、emerge、vimdiff、gvimdiff、ecmerge、opendiff

变基

把一条分支上的修改在另一条分支末梢重现

git rebase <变基到的分支末梢>

出现冲突

修改

git add

git rebase --continue

实现原理

分支A、B,分叉点Y

在分支B上告诉git变基到A的末梢

git将从Y到B的当前末梢间的所有提交顺序加到A的末梢

形成新的分支B及其末梢

分支A机器末梢不变

git rebase --onto <分支A> <分支B> <分支C>

将<分支C>从<分支B>脱离,移动到<分支A>

示例:git rebase --onto master contacts search

历史记录

显示工作目录树状态

git status

日志

git log

-num:限制log输出条数

--pretty=

oneline

每个提交单行显示

format:"%h %s"

格式化输出

-p:显示版本间差异

--stat:显示改动行数统计

--name-status:显示改动文件名称和状态

<hash码>:显示指定版本

至少4位

无论几位都会设法匹配

一般7-8位即可保证唯一性

指定查找范围

--since

最近一段时间

示例:git log --since="5 hours"

git能接受大多数英文格式日期

--before

一段时间以前

<最老版本..最新版本>

指定两个版本间(左开右闭)为查找范围

示例

git log 18f822e..0bb3dfb

git log 18f822e..HEAD

git log 18f822e..

同HEAD

git log 1.0..HEAD

可以使用标签名

注意

指定版本不存在时,会得到“未知版本”报错

-C -C -p

检测文件的复制

日志格式

40位SHA-1

提交者

提交时间

留言

日志浏览

j:向下

k:向上

q:退出

查看特定代码块历史信息

git blame

用法

git blame <文件名>

git blame -L <开始>,<结束> <文件名>

结束可以为行数

可以使用RE

可以指定查找范围

git blame -M <文件名>

检测同一文件内移动或复制的代码行

git blame -C -C <文件名>

查看文件间的复制

示例

git blame index.html

git blame -L 12,14 index.html

git blame -L 12,+2 index.html

git blame -L "/<\/body>/",+2 index.html

git blame -L "/<\/body>/",-2 4333289e^ -- index.html

脱字符表示版本库中第一个提交

改写历史记录

场景

给历史记录重新排序

编辑器中将提交重新排序

将多个提交压合成一个提交

将提交B移到提交A后的一行,将B的pick改为squash

保存退出,变基前弹出编辑器,编辑压合后的留言

将一个大的提交拆分成多个提交

将提交的pick修改成edit,保存退出,变基启动

运行到edit行时git会暂停给出提示

git reset分解提交,即撤销该提交,创建两个独立提交

git rebase --continue

git rebase -i

交互式rebase

查看修改内容

git diff:显示工作目录树中未被暂存的改动

git diff --cached:显示暂存区和版本库的区别

git diff HEAD:显示工作目录树与版本库的差别

指定版本范围

同log

git diff --stat <范围>

默认值为当前工作目录树

统计代码变更统计数据

重现隐藏的历史

git reflog

恢复方法

检出/创建分支

配置

gc.reflogExpireUnreachable:改变有效期

本地版本库

标签

打标签

git tag <标签名> <希望打标签的点(可选,默认为当前工作目录树)>

查看标签列表

git tag

注意

只读

检出标签版本后,处于no branch状态,无法提交和跟踪改动,需要创建新分支

发布分支

即将要发布代码的地方

注意

通常少许改动,侧重于bug和逻辑修正,很少添加新功能

修正时基于标签创建一个新分支,以RB_为前缀

通常以RB_为前缀

持续时间不长,通常只用于发布代码的最终测试期间

一旦版本发布,应使用标签标记,删除分支

记录和跟踪多个项目

多个项目共享一个版本库

项目需要统一的历史记录时适用

这些组件同时发布

多项目多版本库

小项目需单独发布时

git子模块

跟踪外部版本库,允许在某个版本库里再存储一个版本库,并且完全独立

查看

git submodule

hash码前

有-表示未初始化

有+表示子模块不是“容器”版本库记录的子模块版本

添加

git submodule add <源版本库> <存储该版本库的路径>

初始化:git submodule init <子模块>

克隆含子模块的版本库

首先克隆版本库

初始化:git submodule init hocus

git submodule update <源版本库>

改变子模块版本

注意

git子模块不会自动引用版本库最新提交

添加时git总是用源库的HEAD

方法

切换到子模块目录下

检出

如:git checkout HEAD^

暂存

提交

注意

调用git add时结尾处不要有\

结尾的\被视为将源库的全部文件添加到当前库,而不是子模块引用的版本

git submodule update会覆盖本地子模块中所有没提交的内容

改动子模块前要检出要使用的子模块分支

子模块提交修改要确保送回远程版本库

远程版本库

git提供的网络协议

SSH

<用户名>@<服务器名>/版本库路径

示例:git@github.com/tswicegood/mysite.git

注意

如果使用本机登录名作为用户名,则不用指定用户名

一般使用SSH用户更新推入版本库

git

<协议>://<服务器名>/<版本库路径>

示例:git://github.com/tswicegood/mysite.git

特点

无须加密

速度快

匿名

一般为只读的,用于将更新拖入本地

防火墙可能受限

HTTP/HTTPS

示例:http://github.com/tswicegood/mysite.git

特点

通信效率最低

能通过严格的防火墙

易于架设

github不支持

克隆远程版本库

示例:git clone git://github.com/tswicegood/mysite.git mysite-remote

参数

远程版本库的位置

存放该版本库的本地目录(可选)

--depth <num>:只下载最近num个提交的历史记录

版本库同步

git fetch

更新远程分支,但不会把远程分支的修改合并到本地分支

git pull

更新远程分支,然后合并

参数

远程版本库名称

要拖入的远程分支名(不用加origin/)

注意

可以像检出本地分支一样检出远程分支,但不应修改

如果要修改,应先建立一个本地分支,再进行修改

推入改动

git push

不带参数推入默认版本库origin中,并把本地版本库当前分支变更推入远程版本库对应分支

只会推入已检入的改动

--dry-run:查看推入哪些提交

参数与pull相同

注意

一个版本库经常被用来接收推入,则最好不要有本地改动,可以在git init时加上--bare

添加新的远程版本库

注意

本地版本库中,远程版本库别名默认为origin

给远程版本库起别名

git remote add origin git@example.com:/repos/pocud.git

git remote

不带参数:查看本地创建的全部远程版本库别名

show <name>:查看某个远程版本库信息

rm:删除别名

prune:删除远程版本库已不存在的分支

文件

创建归档文件

示例

git archive --format=zip --prefix=mysite-1.0/ 1.0 > mysite-1.0.zip

git archive --format=tar --prefix=mysite-1.0/ 1.0 | gzip > mysite-1.0.tar.gz

参数

--format

归档格式

tar、zip

--prefix

指明包中所有东西放入的目录

要归档的标签名

压缩结果重定向

| gzip > mysite-1.0.tar.gz

> mysite-1.0.zip

文件重命名和移动

git mv <原文件名> <新文件名>

复制

不提供文件复制命令

不需要复制命令

忽略文件

把文件名加入版本库的.gitignore文件中

版本库级别

把文件名加入.git/info/exclude

本地级别

高阶功能

压缩版本库

原因

git版本库存储了所有东西,一些无用信息被留下了

节约磁盘空间

git gc

--aggressive:可进一步优化,但增加时间

二分查找

目的

定位哪个历史版本引入了bug

git bisect

基于一个已知的坏提交和一个已知的好提交

过程

移到坏的提交

git bisect start:开始查找

git bisect bad

git bisect good <某一个提交或标签>

git会进入两点中间的地方检出

如果提交是坏的,标记git bisect bad

如果提交是好的,标记git bisect good

找到问题点后,git bisect reset回到出发点,进行修改

git bisect visualize

可视化历史记录

git bisect log

显示提交的好坏标记

修改

将log存储成一个文件,删除错误的标识及其后记录

git bisect replay <某一文件>

自动化测试

git bisect run <脚本名>

构建脚本的返回值

通过:0

失败:正数(通常是1)

跳过:125

迁移到git

SVN

方法

从SVN导入所有历史记录到git,使用git作为主要的版本控制工具

保持SVN为上游版本库

工具

git-svn

检查可用性

git svn --version

导入SVN版本库

git svn clone

如果SVN版本库遵循默认结构,应加参数-s

如果分支和标签地址在不同位置,使用-b和-t参数

主干没有命名为trunk,使用-T指定具体名称

-r:指定从哪个版本开始克隆

示例:git svn clone --prefix svn/ -s svn://svnrepo/sunshine

提交过多的SVN版本库,克隆结束后应使用git gc

与SVN版本库同步更新

git svn fetch

取来远程修改到远程分支,不合并本地分支

git svn rebase

常用

类似于先git svn fetch,再git rebase

将修改推入SVN

git svn dcommit

参数

-n:演练

git%e6%a0%b8%e5%bf%83%e8%af%a6%e8%a7%a3


博主

让学习成为习惯,坚持-共享-开源-自由! 成功者决不放弃,放弃者绝不成功!

相关推荐

嗨、骚年、快来消灭0回复。