目录
17、stash 储藏
用于将更改储藏在脏工作目录中。
git stash list [<options>]
git stash show [<stash>]
git stash drop [-q|--quiet] [<stash>]
git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]
git stash branch <branchname> [<stash>]
git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
[-u|--include-untracked] [-a|--all] [<message>]
git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
[-u|--include-untracked] [-a|--all] [-m|--message <message>]]
[--] [<pathspec>…]]
git stash clear
git stash create [<message>]
git stash store [-m|--message <message>] [-q|--quiet] <commit>
17.2 描述
-
当要记录工作目录和索引的当前状态,但想要返回干净的工作目录时,使用
git stash
保存本地修改,并恢复工作目录以匹配HEAD
提交; -
list
列出所储藏的修改,show
进行检查,apply
恢复,默认情况下,储藏列表”分支名称上的 WIP “,但可以在创建一个消息时在命令行上给出具体描述性的消息; -
创建的最新储藏存储在
refs/stash
中,这个引用中的反垃圾中会发现较旧的垃圾邮件,并且可以使用通常的 reflog 语法命名(stash@{0}
是最近创建的垃圾邮件),也可以通过指定存储空间索引来引用锁存。
17.3 基本用法
- 拉取到一颗肮脏树
当发现本地的更改与上游的更改冲突时,git pull
拒绝覆盖您的更改,此时可以隐藏更改,执行 git pull
,再解压缩:
git pull
...
file foobar not up to date, cannot merge.
$ git stash
$ git pull
$ git stash pop
- 工作流中断
当要处理紧急的事务从而不得不中断自己的工作流程时,应该提交临时分支来存储更改并返回原始分支进行紧急修复:
$ git checkout -b my_wip // 临时分支
$ git commit -a -m "WIP" // 临时提交
$ git checkout master // 返回主分支
$ edit emergency fix # 编辑内容 // 紧急修复
$ git commit -a -m "Fix in a hurry" // 提交修复
$ git checkout my_wip // 返回临时分支
$ git reset --soft HEAD^ // 移位值最新的提交的头位置
可使用 git stash
来简化:
$ git stash // 临时储藏
$ edit // 处理
$ git commit -a -m 'fix' // 紧急处理
$ git stash pop // 获取最近一次储藏的内容,之后删除栈中对应的 stash
- 储藏工作
当修改文件后,想要切换分支但不想提交当前进行的工作,此时可以往栈中推送新的储藏:
$ git stash
Saved working directory and index state \
"WIP on master: 049d078 added the index file"
HEAD is now at 049d078 added the index file
(To restore them type "git stash apply")
# 查看现有的储藏
$ git stash list
- 应用存储
若想应用之前的变更,可以通过 apply
进行指定应用,不指定将会使用最近的存储:
$ git stash apply
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
#
# modified: index.html
# modified: lib/simplegit.rb
--重新暂存被暂存的文件
$ git stash apply --index
--移除储藏的文件
$ git stash drop stash@{0}
- 取消储藏
通过取消该储藏的补丁使得取消之前所储藏的修改:
$ git stash show -p stash@{0} | git apply -R
# 不指定储藏的索引将会选择最近的储藏
-- 设置别名
$ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
$ git stash apply
$ #... work work work
$ git stash-unapply
- 储藏中创建分支
当储藏了一些工作之后继续工作,重新储藏将会归并冲突,若想重新检验储藏变更,创建新分支,成功将会丢弃储藏:
$ git stash branch testchanges
18、tag 标签
- 用于创建,列出,删除或验证使用 GPG 签名的标签对象。
git tag [-a | -s | -u <keyid>] [-f] [-m <msg> | -F <file>]
<tagname> [<commit> | <object>]
git tag -d <tagname>…
git tag [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]
[--points-at <object>] [--column[=<options>] | --no-column]
[--create-reflog] [--sort=<key>] [--format=<format>]
[--[no-]merged [<commit>]] [<pattern>…]
git tag -v [--format=<format>] <tagname>…
18.1 描述
-
创建标签可以:用于在开发阶段,某个阶段的完成,创建一个版本,在开发中都会使用到,指向软件开发中的一个关键时期;
-
不能创建已经存在的标签,除非指定
-f
; -
创建标签对象以及一个标签消息:
-a
、-s
或-u <keyid>
,使用-m <msg>
或-F <file>
,否则将启动编辑器自主输入标签消息; -
标签类型:
-
轻量级标签,像不会变化的分支,实际上就是个指向特定提交对象的引用;
-
含附注标签,实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。
-
18.2 基本用法
- 列出已有的标签,也可进行筛选:
$ git tag
$ git tag -l 'v1.4.2.*'
- 创建含附注类型的标签:
$ git tag -a v1.4 -m 'my version 1.4'
# 轻量级标签
$ git tag v1.4-lw
# git show 查看响应标签的版本信息,包括标签对象
--$ git show v1.4
tag v1.4
Tagger: Scott Chacon <1@qq.com>
Date: Mon Feb 9 14:45:11 2009 -0800
my version 1.4
commit 15027951111...3b3ff6
Merge: 4a41117... a611117...
Author: n <1@qq.com>
Date: Sun Feb 18 10:10:10 2009 -0800
- 签署标签:
如果有自己的私钥,还可用 GPG 来签署标签:
$ git tag -s v1.5 -m 'my signed 1.5 tag'
- 删除标签:
$ git tag -d v1.0
- 验证已经签署的标签:
$ git tag -v v1.4
object 883653babd11111116a5c392bb739348b1eb61
type commit
tag v1.4
tagger 1C 1<1@1.1> 111111111-0700
GIT 1.4
- 后期标签加注:
$ git tag -a v1.2 9fceb11
- 分享标签:
默认情况下不会把标签传送到远端服务器上,只有通过显式命令才能分享标签到远端仓库。运行 git push origin [tagname]
:
$ git push origin --tags
Counting objects: 50, done.
Compressing objects: 100% (38/38), done.
Writing objects: 100% (44/44), 4.56 KiB, done.
Total 44 (delta 18), reused 8 (delta 1)
To git@github.1/1.git
* [new tag] v0.1 -> v0.1
* [new tag] v1.2 -> v1.2
* [new tag] v1.4 -> v1.4
* [new tag] v1.4-lw -> v1.4-lw
19、fetch 获取
用于从另一个存储库中下载对象和引用。
git fetch [<options>] [<repository> [<refspec>…]]
git fetch [<options>] <group>
git fetch --multiple [<options>] [(<repository> | <group>)…]
git fetch --all [<options>]
19.1 描述
-
从一个或多个其他存储库中获取分支或标签(引用)以及完成其历史所必需的对象**;
-
远程跟踪以更新,需要将这些更新获取回本地;
-
默认情况下还会获取正在获取的历史记录的任何标签;
-
可以从单个命名的存储库或 URL 中,也可以从多个存储库中获取;
-
获取的参考名称以及它们所指向的对象名称被写入到
.git/FETCH_HEAD
中。
19.2 基本用法
- 更新远程跟踪分支:
# 从远程 refs/heads/ 命名空间复制所有分支,并存储到本地 refs/remotes/origin/ 中
$ git fetch origin
- 使用 refspec:
# 从远程分支 pu 和 maint 提取到本地 pu 和 tmp
$ git fetch origin +pu:pu maint:tmp
- 远程分支上窥视:
$ git fetch git://git.1.org/1/git.git maint
# 使用FETCH_HEAD来检查具有git-log的分支
$ git log FETCH_HEAD
- 更新远程分支主机:
$ git fetch <远程主机名>
# 更新所有分支
$ git fetch
# 指定远程主机的指定分支
$ git fetch <远程主机名> <分支名>
# 查看远程分支
$ git branch -a
* master # 本地的当前分支
remotes/origin/master # 远程分支
20、pull 整合
用于从另一个存储库或本地分支获取并集成(整合)到本地分支。
git pull [options] [<repository> [<refspec>…]]
20.1 描述
-
默认模式下,
git pull
是git fetch
后跟git merge FETCH_HEAD
的缩写; -
git pull
使用给定的参数运行git fetch
,并调用git merge
将检索到的分支头合并到当前分支中。
20.2 基本用法
- 将远程主机的分支与本地的分支 master 合并:
$ git pull origin next:master
# 合并当前分支则省略 : 冒号
- 建立追踪关系(tracking)下 pull 可以省略远程分支名:
# 手动建立追踪关系
$ git branch --set-upstream master origin/next
# 合并
$ git pull origin
# 若当前分支只有一个跟踪分支,则可以省略远程主机名
$ git pull
# 采用 rebase 模式
$ git pull --rebase <远程主机名> <远程分支名>:<本地分支名>
20.3 pull 与 fetch 的区别
- git fetch :相当于是从远程获取最新到本地,不会自动合并;
$ git fetch origin master # 下载最新版本都本地
$ git log -p master..origin/master # 比较分支差别
$ git merge origin/master # 合并
- git pull :相当于是从远程获取最新并 merge 到本地;
git pull origin master
21、push 更新推送
用于将本地分支的更新,推送到远程主机。格式与 pull 相似。
$ git push <远程主机名> <本地分支名>:<远程分支名>
git push [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
[--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose]
[-u | --set-upstream] [--push-option=<string>]
[--[no-]signed|--sign=(true|false|if-asked)]
[--force-with-lease[=<refname>[:<expect>]]]
[--no-verify] [<repository> [<refspec>…]]
21.1 描述
-
使用本地引用更新远程引用,同时发送完成给定引用所需的对象;
-
可以在每次推入存储库时,通过在那里设置挂钩触发一些事件;
-
当不指定使用
<repository>
参数时,将查询当前分支的branch.*.remote
以此确定位置。
21.2 基本用法
- 删除远程分支:
# 推送本地空的分支
$ git push origin :master
# 等同于
$ git push origin --delete master
-u
指定默认主机:
$ git push -u origin master # 后面可直接使用 git push
- 更改默认推送方式
simple
方法( V2.0 之前默认 matching ):
$ git config --global push.default matching
# 或者
$ git config --global push.default simple
- 推送更新
# 推送所有远程主机
$ git push --all origin
# 强制推送,产生一个 非直进式 合并
$ git push --force origin
# 推送标签,默认不推送
$ git push origin --tags
# 将远程分支推送到远程同名下
$ git push origin HEAD
# 将当前分支推送到源存储库中的远程引用匹配主机
$ git push origin HEAD:master
- 异分支推送、补充与覆盖:
# 推送新分支
$ git push origin lbranch-1:refs/rbranch-1
# 补充原有分支
$ git rebase rbranch-1
$ git push origin lbranch-2:refs/rbranch-1
# 覆盖远程分支
$ git push -f origin lbranch-2:refs/rbranch-1
--或者
$ git push origin :refs/rbranch-1 //删除远程的rbranch-1分支
$ git push origin lbranch-1:refs/rbranch-1
- 查看 push 结果:
$ gitk rbranch-1
- 标签推送与删除:
$ git push origin tag_name
# 删除远程标签
$ git push origin :tag_name
22、remote 管理
- 用于管理一组跟踪的存储库。
git remote [-v | --verbose]
git remote add [-t <branch>] [-m <master>] [-f] [--[no-]tags] [--mirror=<fetch|push>] <name> <url>
git remote rename <old> <new>
git remote remove <name>
git remote set-head <name> (-a | --auto | -d | --delete | <branch>)
git remote set-branches [--add] <name> <branch>…
git remote get-url [--push] [--all] <name>
git remote set-url [--push] <name> <newurl> [<oldurl>]
git remote set-url --add [--push] <name> <newurl>
git remote set-url --delete [--push] <name> <url>
git remote [-v | --verbose] show [-n] <name>…
git remote prune [-n | --dry-run] <name>…
git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)…]
22.1 基本用法
- 列出存在的远程分支:
git remote
- 列出详细信息:
# --verbose 显示对应的克隆地址
$ git remote -v
- 添加新的远程并检出一个分支:
# taging 指代对应的仓库
$ git remote add staging git://git.kernel.org/.../gregkh/staging.git
# 列出分支
$ git remote
# 更新远程分支
$ git fetch staging
# 查看分支关系
$ git branch -r
# 切换到远程分支
$ git checkout -b github/master
- 模仿 clone ,但只跟踪选定分支
$ git remote add -f -t master -m master origin git://example.com/git.git
$ git merge origin
23、submodule 管理子模块
- 用于初始化、更新或检出子模块。
git submodule [--quiet] add [<options>] [--] <repository> [<path>]
git submodule [--quiet] status [--cached] [--recursive] [--] [<path>…]
git submodule [--quiet] init [--] [<path>…]
git submodule [--quiet] deinit [-f|--force] (--all|[--] <path>…)
git submodule [--quiet] update [<options>] [--] [<path>…]
git submodule [--quiet] summary [<options>] [--] [<path>…]
git submodule [--quiet] foreach [--recursive] <command>
git submodule [--quiet] sync [--recursive] [--] [<path>…]
git submodule [--quiet] absorbgitdirs [--] [<path>…]
23.1 使用场景
当项目越来越多的时候,常常会需要提取一个公共的库给多个项目使用,此时会有:
-
如何在 git 项目中导入库?
-
库在其他项目中被修改了可以更新到远程代码库?
-
其他库如何获取库的最新的提交?
-
如何在 clone 的时候自动导入库?
23.2 描述
submodule 是一个很好的多项目使用共同类库的工具。
-
允许类库项目为 repository,子项目为一个单独的 git 项目存在父项目中,子项目可以有自己的独立的
commit
,push
,pull
; -
父项目以 Submodule 的形式包含子项目,父项目可以指定子项目 header;
-
父项目中的提交信息包含 Submodule 的信息,clone 父项目时可以把 Submodule 初始化。
23.3 基本用法
-
添加子模块:
- 添加名为 “DbConnector” 的库,默认情况下子模块会将子项目放到一个与仓库同名的目录:
$ git submodule add http://github.com/chaconinc/DbConnector
- 此时会新增两个文件,包括
.gitmodules
文件,该配置文件保存了 URL 与已经拉取的本地目录之间的映射:
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitmodules
new file: DbConnector
$ cat .gitmodules
[submodule "DbConnector"]
path = DbConnector
url = http://github.com/chaconinc/DbConnector
如果有多个子模块,该文件就会有多条记录;
如果
.gitignore
文件一样受到版本控制;
-
克隆含有子模块的项目:
- 项目中有 DbConnector 目录,不过是空的,需要进行初始化:
$ ls -la
drwxr-xr-x 13 schacon staff 442 Sep 17 15:21 .git
-rw-r--r-- 1 schacon staff 92 Sep 17 15:21 .gitmodules
drwxr-xr-x 2 schacon staff 68 Sep 17 15:21 DbConnector
...
git submodule init
用来初始化本地配置文件,而git submodule update
则从该项目中抓取所有数据并检出父项目中列出的合适的提交:
$ git submodule init
Submodule 'DbConnector' (http://github.com/chaconinc/DbConnector) registered for path 'DbConnector'
$ git submodule update
Cloning into 'DbConnector'...
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 11 (delta 0), reused 11 (delta 0)
Unpacking objects: 100% (11/11), done.
Checking connectivity... done.
Submodule path 'DbConnector': checked out 'c3f01dc8862123d317dd46284b05b6892c7b29bc'
- 也可以在 clone 时利用
--recursive
进行自动初始化并更新仓库中的每一个子模块:
$ git clone --recursive http://github.com/chaconinc/MainProject
- 删除 submodule:
# 不支持直接删除,需手动删除:
git rm --cached pod-library
rm -rf pod-library
rm .gitmodules
更改git的配置文件config:
vim .git/config
# 删除后进行提交远程服务器
git commit -a -m 'remove pod-library submodule'
24、show 显示
- 用于显示各种类型的对象。
git show [options] <object>…
24.1 描述
-
显示一个或多个对象(
blobs
,树,标签和提交); -
显示日志消息和文本差异,还以
git diff-tree --cc
生成的特殊格式呈现合并提交; -
显示标签消息和引用对象;
-
显示树的名称(相当于
git ls-tree
和--name-only
); -
显示 blobs 的普通的内容;
-
通常用来显示提交引入的更改。
24.2 基本用法
- 显示标签及其指向对象:
$ git show v1.0.0
- 显示标签指向的树:
$ git show v1.0.0^{tree}
- 显示标签指向的提交的主题:
$ git show -s --format=%s v1.0.0^{commit}
- 显示 README 文件内容,next 分支的第10次提交的内容:
$ git show next~10:README
- 将 Makefile 的内容连接到分支主控的头部:
$ git show master:Makefile master:t/Makefile
25、shortlog 汇总
- 用于汇总 git 日志输出。
git log --pretty=short | git shortlog [<options>]
git shortlog [<options>] [<revision range>] [[\--] <path>…]
如果在命令行上没有传递修订版本,并且标准输入不是终端或没有当前的分支,则 git shortlog
将输出从标准输入读取的日志的摘要,而不引用当前存储库。
25.1 基本用法
- 显示用户提交次数以及提交的注释:
$ git shortlog -s -n
135 Tom Preston-Werner
15 Jack Danger Canty
-s
省略每次 commit 注释仅仅返回一个简单统计;
-n
按照 commit 数量从多到少进行排序。
26、describe 显示最近标签
显示离当前提交最近的标签。
简介:
git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>…]
git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]
26.1 描述
-
查找从提交可访问的最新标记;
-
如果标签指向提交,则只显示标签。 否则,它将标记名称与标记对象之上的其他提交数量以及最近提交的缩写对象名称后缀;
-
默认情况下(不包括
--all
或--tags
) git 描述只显示注释标签。
26.2 基本用法
- 显示标签描述信息:
$ git describe --tags
tag1-2-g026498b
2
:表示自打tagtag1
以来有2
次提交(commit);
g026498b
:g 为git的缩写,在多种管理工具并存的环境中很有用处;
27、rebase 合并修改
- 在另一个分支基础之上重新应用,用于把一个分支的修改合并到当前分支。
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>]
[<upstream> [<branch>]]
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>]
--root [<branch>]
git rebase --continue | --skip | --abort | --quit | --edit-todo
27.1 示例
-
merge 合并:
- 基于远程分支 origin 新建一个分支 mywork:
- 在 mywork 分支上做一些修改生成两个提交:
- 此时用 pull 命令把 origin 分支上的修改拉下来与自己的修改进行合并
# 1.
$ git checkout -b mywork origin
# 2.
$ vi file.txt
$ git commit
# 3.
$ git pull ...
-
rebase 合并:
- 若是想分支历史合并,使得远程记录进行合并,则用 rebase 合并:
$ git checkout mywork
$ git rebase origin
该命令会把”mywork
“分支里的每个 commit 取消掉,并临时保存为补丁(patch 在”.git/rebase
“),然后把”mywork
“ 更新 ”origin
“ ,最后把补丁应用到”mywork
“上。
更新 mywork 之后,会指向新的提交,丢弃旧的提交。
运行垃圾收集命令(pruning garbage collection), 删除被丢弃的提交。
rebase 过程中也会出现冲突,git 会停止 rebase,解决完冲突后,add 更新内容的索引,无需 commit ,只需要:
$ git rebase --continue
此时 git 会 apply 余下的 补丁。
- 可以用
--abort
来终止 rebase 操作。并且 mywork 会回到 rebase 开始前的状态:
$ git rebase --abort