补丁(patch)是基于提交的改动的内容所生成的文件。比如为修一个bug所做的修改,制作成patch,然后将该补丁应用到版本库以解决bug。
# 生成patch
git diff ./ > xxx.patch #将差异的内容制作成patch
mkdir update && git diff commit-id-time1 commit-id-time2 --name-only | xargs -i cp '{}' ./update/ --parents #制作patch 把两个commit-id 之间修改的文件复制到update目录中 而且会把中间的目录也一并生成
# 打patch
patch -p1 < xxx.patch
PS:如果可以直接获取到仓库,使用git命令git fetch
+ git cherry-pick
可以达到同样的效果。
子模块允许你将一个 Git 仓库当作另外一个Git仓库的子目录。这允许你克隆另外一个仓库到你的项目中并且保持你的提交相对独立。配置文件在.gitmodules
1)命令速查
git submodule --help # 查看说明
## 克隆代码时带上子模块
git clone --recurse-submodules <repository>
## 初始化本地.gitmodules文件
git submodule init
## 添加子模块
git submodule add <repository> [<path>]
## 拉取所有子模块
git submodule foreach git pull
## 更新子模块
git submodule update --init --recursive --remote [<path>]
git submodule foreach git submodule update
## 将子模块切到指定分支
git submodule set-branch -b master [<path>]
2)相关案例
CASE01:切换带有子模块的分支
CASE02:子模块提交被覆盖
CASE03:子目录转换到子模块
贮藏(stash)会处理工作目录的脏的状态——即跟踪文件的修改与暂存的改动——然后将未完成的修改保存到一个栈上, 而你可以在任何时候重新应用这些改动(甚至在不同的分支上)。或在清理(clean)文件。
1)命令速查
$ git stash push # stash跟踪文件的修改与暂存的改动
$ git stash push --keep-index # --keep-index 选项使存储的同时保留索引。
$ git stash push --all # -u 选项存储untracked文件,
$ git stash push -u # stash全部文件(包括被忽略文件)
$ git stash list # 列出当前的stash
$ git stash apply # 应用stash, 加上--index 选项可以让之前暂存的文件重新暂存
$ git stash drop stash@{0} # 移除stash,
$ git stash pop # 应用stash@{0},并移除它
$ git stash branch dev # 创建新分支dev,然后应用stash,然后drop stash
$ git clean -f -d # 移除工作目录中所有未追踪的文件以及空的子目录(不包括被忽略文件)
$ git clean -n # 演戏以下,加-n参数
$ git clean -n -x # -x选择清理忽略文件
$ git clean -x -i # -i交互模式
revert还原提交,撤销已经存在的commit的所有更改,原来的commit将保留,并用新commit来记录还原后的结果。git help revert
命令查看具体描述。
1)命令速查
git revert HEAD # 撤销当前HEAD指向的patch上的更改
git revert commit # 撤销制定commitid表示的patch上的更改
# merge之后的revert
git revert -m 1 HEAD # HEAD指向的节点有两个父节点,-m 1保留父节点1,撤销父节点2带来的改变
git reset
将当前HEAD重置为指定状态。git help reset
命令查看具体描述。
1)前置概念
理解git三棵树,即
# - HEAD,永远指向当前分支的最新一笔提交
# - Index,索引(暂存区)
# - Work Directory,工作目录
#git 底层命令
git cat-file -p HEAD #显示HEAD内容
git ls-tree -r HEAD #显示树对象的内容
git ls-files -s #显示索引(Index)的所有文件信息
tree #查看当前工作目录
2)使用准则
git --hard reset
之前请考虑一下。如果由于执行这个选项导致工作目录中文件(文件已经提交)被覆盖,可以尝试git reflog
找回。3)命令速查
# 作用于某个patch
git reset --soft [patch] #移动HEAD的指向,不改变Index和Work Directory
git reset --mixed [patch] #(默认reset)移动HEAD的指向,改变Index,但不改变Work Directory
git reset --hard [patch] #移动HEAD的指向,改变Index和Work Directory
# 作用于某个path/file
git reset [path/file] #通过当前HEAD指向的patch改变当前Index(恢复暂存区)
git reset [patch] [path/file] #通过指定patch改变当前Index
# 压缩提交
git reset --soft [patch] #HEAD移动到压缩提交的前一个patch,Index和Work Directory不变
git commit #通过Index创建新的patch
rebase也是整合不同分支的方法,和merge不同的是它会改变提交历史。git help rebase
命令查看具体描述。
假设当前HEAD指向topic
分支,下面执行rebase命令(将topic上的patch打到master上,并改变历史),使用git rebase master
rebase前:
A---B---C topic
/
D---E---F---G master
rebase后:
A'--B'--C' topic
/
D---E---F---G master
1)命令速查
git rebase master topic #master是基底分支,将topic分支上的修改在master上重放
git rebase --onto master server client #选中在 client 分支里但不在 server 分支里的修改,将它们在 master 分支上重放
wjf@ubuntu:base$ pwd
/home/wjf/miui/umi-q/frameworks/base
wjf@ubuntu:base$ repo info .
Manifest branch: miui-q-umi-stable
Manifest merge branch: refs/heads/stable
Manifest groups: all,-notdefault
----------------------------
Project: platform/frameworks/base
Mount path: /home/wjf/miui/umi-q/frameworks/base
Current revision: miui-q-umi-stable
Local Branches: 0
----------------------------
wjf@ubuntu:base$ git push ssh://[email protected]:29418/platform/frameworks/base HEAD:refs/for/miui-q-umi-stable
git push
git语法表示远程推送,git push help
查看详细情况ssh://[email protected]:29418/platform/frameworks/base
表示使用ssh协议访问gerrit服务器的29418端口,通过url定位到frameworks/base这个目录,是要推送的目录HEAD:refs/for/miui-q-umi-stable
,HEAD指向当前的本地分支,refs/for/miui-q-umi-stable表示远程分支名。ps: 在修改目录下,git remote -v命令查看代码服务器的git仓库的链接,repo info .获取gerrit仓库远程提交点(分支名)
工具用来合并一个或者多个分支到你已经检出的分支中。 然后它将当前分支指针移动到合并结果上。git help merge
命令查看具体描述。
将topic
分支merge到master
分支上(更新master分支),使用git merge topic
合并前:
A---B---C topic
/
D---E---F---G master
合并后:
A---B---C topic
/ \
D---E---F---G---H master
git stash
储藏本地的修改git status
查看分支状态,git diff
显示工作区文件变化1)命令速查
$ git merge slave # merge slave分支到当前HEAD分支, --no-ff
$ git merge slave --no-ff # 不使用fast-forward模式,merge同时创建一个新的cmomit patch
$ git merge slave --allow-unrelated-histories #
$ git merge -Xignore-space-change whitespace # 忽略空白merge
$ git merge --abort # (merge失败)恢复到合并前的状态
$ git merge --continue # 冲突后执行
显示项目提交历史,通过参数选项可以控制log显示的方式。git help log
查看具体描述。
git log 有两个高级用法:一是自定义提交的输出格式,二是过滤输出哪些提交。这两个用法合二为一,你就可以找到你项目中你需要的任何信息。
1)命令速查
# 常规使用
git log --oneline --graph --all #简略显示各种分支的patch记录,个人比较下常用这个命令
git log --stat # 显示每次提交的文件修改统计信息。
git log -p # 按补丁格式显示每个提交引入的差异。
# 定制化输出
# - --date=format定制作者修订日期格式
# - --pretty=format定制log记录显示
# - --graph图形显示分支与合并历史
# - --all显示所有分支
git log --pretty=format:"%h %s" --graph
git log --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:"%h-%an-%ad-%ae" --graph --all
# 过滤出自己想要看到的log
git log -3 #按次数,最近3次提交log
git log --since=2.weeks #按时间,最近两周提交log
git log --until=2020-03-20 #按时间,2020-03-20前的提交log
git log --grep="update" #仅显示提交说明中包含"update"的提交
# 如果要在 Git 源码库中查看 Junio Hamano 在 2008 年 10 月其间, 除了合并提交之外的哪一个提交修改了测试文件,可以使用下面的命令:
git log --pretty="%h - %s" --author='Junio C Hamano' --since="2008-10-01" \
--before="2008-11-01" --no-merges -- t/
5610e3b - Fix testcase failure when extended attributes are in use
acd3b9e - Enhance hold_lock_file_for_{update,append}() API
f563754 - demonstrate breakage of detached checkout with symbolic link HEAD
d1a43f2 - reset --hard/read-tree --reset -u: remove unmerged new paths
51a94af - Fix "checkout --track -b newbranch" on detached HEAD
b0ad11e - pull: allow "git pull origin $something:$current_branch" into an unborn branch
从远程取最新的patch或者分支,引用的信息记录到.git/FETCH_HEAD
这个文件中。可以借助git fetch --help
查看具体描述。可以操作一个分支git pull = git getch + git merge
,也可以单独pick一个patchgit fetch + git cherry-pick
。
### 从gerrit上取一个patch,然后pick到当前分支
git fetch ssh://[email protected]:29418/device/xiaomi/merlin refs/changes/17/909617/1
git cherry-pick FETCH_HEAD
### 获取远程库的分支更新,然后merge到本地分支
git fetch origin master:tmp #从远程仓库master分支获取最新,在本地建立tmp分支
git diff tmp #將當前分支和tmp進行對比
git merge tmp #合并tmp分支到当前分支
使用git blame
能显示任何文件中每行最后一次修改的提交记录。git blame --help
查看具体描述
mi@ubuntu:base$ git blame Android.bp -L 230,231 #查看Android.bp的230-231行提交记录,
#commit id #提交者 #时间 #行 #内容
7c469179ce2a (junyulai 2019-01-16 20:23:34 +0800 230) "core/java/android/net/ISocketKeepaliveCallback.aidl",
e40eab608af2 (Benedict Wong 2018-11-14 17:50:13 -0800 231) "core/java/android/net/ITestNetworkManager.aidl",
git bisect
能在commit区间中检出中间的patch,通过不断地二分查找,最终定位到带bug的patch
# 开始
$ git bisect start # 启动二分
$ git bisect bad # 当前提交有bug
$ git bisect good <good_commit> #指定已知的最后一次正常状态是哪次提交
# 测试 --> 二分判断
$ git bisect good # 当前提交无bug
$ git bisect bad # 当前提交有bug
# 结束
$ git bisect reset