Git 和 Repo常用命令
这篇博客总结的也不错:
- 8 Tips to help you work better with Git
- git常用及进阶命令总结
- Git与Repo入门
- 45 个 GIT 经典操作场景,专治不会合代码
- git-cheat-sheet.pdf
- Git tips and tricks
- Git远程库代码回退
- Git帮助手册
- Git 开发必备 .gitignore 详解
- 或者使用oh-my-zsh,它会自动配置很多实用的git别名
初始环境配置
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
git config --global core.editor vim
git config --global color.ui true
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
# Delete local branches that have been removed from remote on fetch/pull
git config --global fetch.prune true
git config --global alias.show-graph 'log --graph --abbrev-commit --pretty=oneline'
更多配置,请参考:Git tips and tricks
- 下面是一份配置好的.gitconfig:
[user]
name = Peng Donglin
email = dolinux.peng@gmail.com
[alias]
ci = commit
st = status
co = checkout
br = branch
d = difftool
lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset' --abbrev-commit --date=relative
lol = log --graph --decorate --pretty=oneline --abbrev-commit
[core]
editor = vim
[color]
ui = true
[sendemail]
smtpserver = /usr/bin/msmtp
confirm = auto
[diff]
tool = vimdiff
[difftool]
prompt = false
[merge]
tool = vimdiff
[mergetool]
prompt = false
- 使用vimdiff作为 git diff工具
git config --global diff.tool vimdiff
git config --global difftool.prompt false
git config --global alias.d difftool
然后使用 git d
打开对比代码,然后用 :wq
继续比较下一个文件。
git difftool $start_commit..$end_commit -- path/to/file
git merge
时使用vimdiff
git config --global merge.tool vimdiff
git config --global mergetool.prompt false
常用的命令
gitignore规则
- .gitignore文件配置的一些规则
*.a # 忽略所有 .a 结尾的文件
!lib.a # 但 lib.a 除外
/TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
build/ # 忽略 build/ 目录下的所有文件
doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
差异
-
查看已暫存起來的文件跟上次提交時的快照之間的差異
git diff --cached
-
查看還沒有暫存起來的改動
git diff
-
查看两次提交之间某个文件的差异
git diff $start_commit..$end_commit -- path/to/file
-
查看两次提交之间的差异
git diff $start_commit..$end_commit
删除
-
删除在远程仓库已经不存在的本地分支
To remove all tracking branches that you have locally but are no more present in the remote repository (origin):
git remote prune origin
Use the --dry-run flag to only see what branches will be pruned, but not actually prune them:
git remote prune origin --dry-run
-
將已經提交的文件從Git倉庫中刪除,但是本地還保留該文件,即取消跟蹤某個文件
git rm --cached readme.txt
-
批量删除分支
git branch |grep 'branchName' |xargs git branch -D
提交记录
- 查看某次提交改動了那些文件
git log --stat
git log --stat dd257933fa4b9fea66a1195f8a15111029810abc -1
- 简要列出最近的提交commet
$git log --pretty=oneline
694d0d0bb2030d2e36df73e2d23d5770511dbc8d Linux 4.8-rc2
0043ee40f98d15a50721fbd5dbf7c7797f8d03cd Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
4ef870e373382f18de214f61e5d5eb83b62b7aa5 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu
- 列出某人的提交記錄
$git log --author="Linus Torvalds"
$tig --author="xxx"
- 如果想過濾掉這個人的merge記錄,可以用
git log --author="Linus Torvalds" --no-merges
复位
- 取消已經暫存的某個文件
git reset HEAD readme.txt
远程仓库
- 查看遠程倉庫的信息
git remote show origin
blame
- 查看某個文件的若干行的改動記錄
git blame -L 12,22 simplegit.rb
git blame -w # ignores white space
git blame -M # ignores moving text
git blame -C # ignores moving text into other files
checkout
- 获得某次提交的某个文件
git checkout commit-id file_name
push
- 将本地的tags全部push到远程仓库
git push origin --tags
- 将本地分支全部push到远程仓库
git push --all origin
git clean的用法
git clean -n 显示 将要 删除的 文件 和 目录
git clean -f 删除当前目录下所有没有track过的文件. 他不会删除.gitignore文件里面指定的文件夹和文件, 不管这些文件有没有被track过.
git clean -df 删除当前目录下没有被track过的文件和文件夹
git clean -xfd 删除当前目录下所有没有track过的文件. 不管他是否是.gitignore文件里面指定的文件夹和文件.
用Git打包文件
git archive --format=tar.gz --prefix=Linux-3.16/ v3.16 > Linux-3.16.tar.gz
git archive --format=tar.gz --prefix=Linux-4.17/ 29dcea88779c856c7dc92040a0c01233263101d4 > Linux-4.17.tar.gz
git rebase用法,用于修改历史提交记录
- 效果1
加入当前在topic分支上,想实现下面的效果
将
A---B---C topic
/
D---E---F---G master
变成:
A'--B'--C' topic
/
D---E---F---G master
可以使用下面的任意一个命令:
git rebase master
git rebase master topic
- 效果2
假如当前在topic分支,下面A'
和A
是两个相同的patch,不过commit id不同。
将:
A---B---C topic
/
D---E---A'---F master
变成:
B'---C' topic
/
D---E---A'---F master
可以使用下面的命令:
git rebase master
- 效果3
将:
o---o---o---o---o master
\
o---o---o---o---o next
\
o---o---o topic
变成:
o---o---o---o---o master
| \
| o'--o'--o' topic
\
o---o---o---o---o next
可以使用下面的命令:
git rebase --onto master next topic
- 效果4
将:
H---I---J topicB
/
E---F---G topicA
/
A---B---C---D master
变成:
H'--I'--J' topicB
/
| E---F---G topicA
|/
A---B---C---D master
可以使用下面的命令:
git rebase --onto master topicA topicB
- 效果5
相当于效果4的特例,用于移除一些提交, 将:
E---F---G---H---I---J topicA
变成:
E---H'---I'---J'
可以使用如下命令:
git rebase --onto topicA~5 topicA~3 topicA
修改commit的提交顺序
搜索commit
- [7.5 Git Tools - Searching](https://git-scm.com/book/en/v2/Git-Tools-Searching "7.5 Git Tools - Searching")
- [How to search a Git repository by commit message?](https://stackoverflow.com/questions/7124914/how-to-search-a-git-repository-by-commit-message "How to search a Git repository by commit message?")
- [Search a whole Git repository](https://superuser.com/questions/1008404/search-a-whole-git-repository "Search a whole Git repository")
git log --grep "Call Trace" --all # 搜索commit message
git log -G "xxx" # 搜索diff
# risc-v ftrace 支持相关代码查找方法
git log --oneline --grep="ftrace" arch/riscv/
# 比如,在宕机时的调用栈中有i40e_down和i40e_remove字段,那么可以用下面的命令搜索是否有跟这个字段的提交
$ git log --oneline --grep "i40e_down" --grep "i40e_remove" drivers/net/ethernet/intel/i40e/
6533e558c650 i40e: Fix reset path while removing the driver
5b6d4a7f20b0 i40e: Fix crash during removing i40e driver
b3873a5be757 net/i40e: Fix concurrency issues between config flow and XSK
f980d445e5ae i40e: Add a call to set the client interface down
e108b0e341ec i40e: Setting i40e_down bit for tx_timeout
此外,如果想同时显示过滤出来的提交内容,可以增加-p
参数,如git log --grep "kvm_bios" --oneline --no-merges -p
可以加入--no-merges
把merge提交过滤掉。
搜索提交也可以用git log -p | grep ""
查看一个函数的进化历史
git log -L <start line>,<end line>:file
git log -L :<function name>:file
更换commit的作者
git commit -s --reset-author
git commit -s --author="xxx"
git ignore
- 检查某个文件被ignore的原因
git check-ignore -v tools/perf/include/perf/junk
git worktree
在开发工作中,大家估计都遇到过这样的需求:正在开发的东西不想动,但是需要一个完整工作目录来做测试或者搞一些其他事情。一般来说可以拉个分支,用git stash保存目前的工作区状态,等搞完事情再切回来。但是如果需要两个或者更多个工作区同时搞事情上面的方案就不行。这时候当然可以git clone几个完整仓库副本来搞,但是也很麻烦费事,而且仓库的同步也是个问题。有没有更好的方法呢?在此之前我是不知道的,直到发现了git的一个新的屠龙技——git worktrees工作树功能。
- https://www.cnblogs.com/lxd670/p/17550490.html
- Git屠龙技:使用Git Worktree并行开发测试
- 通过git worktree实现同时在两个分支上进行开发
- Git Worktree 实用指南
配置git email
在给linux kernel提交patch的时候一般都使用git send-email。
可以用用下面的命令安装git send-mail:
sudo apt-get install git-email
- 参考
- laravel gmail 发送邮件失败
- 提交内核补丁到Linux社区的步骤
- Jeff分享:objtrace源码与框架分析 和 如何向Linux内核社区提交patch
- ccproxy windows上用的代理软件(类似linux系统上的squid)
- squid 二级代理
- 提交补丁:如何让你的改动进入内核
- Linux内核补丁提交检查单
- 正确使用邮件列表参与开源社区的协作
- Linux邮件客户端配置信息
- b4 for Linux kernel contributors
- Become a Linux kernel contributor - Part 1
- Become a Linux kernel contributor - Part 2
- Become a Linux kernel contributor - Part 3
- Configure Thunderbird to send patch friendly
- How I use Thunderbird to Write Emails and Review Patches
- https://kernel.org/pub/software/scm/git/docs/git-send-email.html
- 生成补丁
git format-patch --cover-letter --subject-prefix='PATCH' --thread -N #这里的N是你要提取的补丁个数
$ git format-patch -1 --rfc -v 3
v3-0001-bpf-Using-binary-search-to-improve-the-performanc.patch
$ cat v3-0001-bpf-Using-binary-search-to-improve-the-performanc.patch | head -n 10
From 8a21eb3860c8c82fc2511826ffb8277817435076 Mon Sep 17 00:00:00 2001
From: Donglin Peng <dolinux.peng@gmail.com>
Date: Sat, 8 Jun 2024 04:27:55 -0700
Subject: [RFC PATCH v3] bpf: Using binary search to improve the performance of
btf_find_by_name_kind
Currently, we are only using the linear search method to find the type id
下面是.gitconfig
中的配置:
smtpuser = dolinux.peng@gmail.com
smtpserver = smtp.gmail.com
smtpencryption = tls
smtpserverport = 587
;smtppass = xxxx
confirm = auto
上面smtppass是谷歌邮箱的应用密码,可以按照这个链接提示的方法获取
如果需要通过代理访问gmail,可以参考https://www.cnblogs.com/pengdonglin137/articles/15647356.html
不需要使用msmtp,只需要安装和配置一下proxychains,然后使用"proxychains + 发送命令"。
repo 常用命令
-
开启一个新的主题,其实就是每个Project都新建一个分支
repo start <topic_name>
-
在当前目录下初始化repo,会在当前目录生生成一个.repo目录,像Git Project下的.git一样,-u指定url,可以加参数-m指定manifest文件,默认是default.xml,.repo/manifests保存manifest文件。.repo/projects下有所有的project的数据信息,repo是一系列git project的集合,每个git project下的.git目录中的refs等目录都是链接到.repo/manifests下的。
repo init -u <url> [OPTIONS]
-
可以根据当前各Project的版本信息生成一个manifest文件
repo manifest
-
同步Code
repo sync [PROJECT1...PROJECTN]
-
查看本地所有Project的修改,在每个修改的文件前有两个字符,第一个字符表示暂存区的状态
repo status
标志说明:
- | no change | same in HEAD and index |
---|---|---|
A | added | not in HEAD, in index |
M | modified | in HEAD, modified in index |
D | deleted | in HEAD, not in index |
R | renamed | not in HEAD, path changed in index |
C | copied | not in HEAD, copied from another in index |
T | mode changed | same content in HEAD and index, mode changed |
U | unmerged | conflict between HEAD and index; resolution required |
每二个字符表示工作区的状态:
letter | meaning | description |
---|---|---|
- | new/unknown | not in index, in work tree |
m | modified | in index, in work tree, modified |
d | deleted | in index, not in work tree |
-
删除已经merge的分支
repo prune <topic>
-
删除分支,无论是否merged
repo abandon <topic>
-
查看所有分支
repo branch或repo branches
-
查看修改
repo diff
-
上传本地提交至服务器
repo upload
-
对指定的Project列表或所有Project执行命令COMMAND,加上-p参数可打印出Project的路径
repo forall [PROJECT_LIST]-c COMMAND
-
repo forall
撤销整个工程的本地修改:
repo forall -c 'git reset --hard HEAD;git clean -df;git rebase --abort'
把所有的库切换分支:repo forall -c git checkout branch_name
删除所有库的某个分支:repo forall -c git branch -D branch_name
在每个git工程下建立分支:repo forall -c "git co aosp/o-preview -b o-preview"
tig使用
-
下翻半屏:
Ctrl D
或者 空格 -
上翻半屏:
Ctrl U
-
向下按行滚动:
Ctrl E
-
向上按行滚动;
Ctrl Y
-
在修改的代码块之间移动:
@
-
显示行号:
#
在看提交时,有时不知道看了多少,把行号显示出来作为参照。
-
视图最大化: 大
O
-
刷新视图:
R
或者F5
-
分支线条效果切换:
G
分支线条效果分为V2、V1和no三种。使用G
可以在这三种之间切换。默认是V2,分支线条有时会影响阅读体验,比如:
分支线条把正常的commit信息都挤到屏幕之外了,下面是关闭之后的效果:
如果commit信息被分支线条挤走,可以使用左右方向键来移动屏幕
- 显示commitid:
X
默认没有显示commit id,可以按大X
键进行显示。
40adaf5 2022-11-18 10:15 +0900 Masami Hiramatsu (Google) │ o tracing/eprobe: Fix eprobe filter to make a filter correctly
342a4a2 2022-11-18 10:15 +0900 Rafael Mendonca │ o tracing/eprobe: Fix warning in filter creation
- 切换日期显示方式:
D
下面是同一次提交的不同日期显示效果。
2022-11-18 10:15 +0900 Masami Hiramatsu (Google) │ o tracing/eprobe: Fix eprobe filter to make a filter correctly
6 days ago Masami Hiramatsu (Google) │ o tracing/eprobe: Fix eprobe filter to make a filter correctly
6D Masami Hiramatsu (Google) │ o tracing/eprobe: Fix eprobe filter to make a filter correctly
2022-11-18 Masami Hiramatsu (Google) │ o tracing/eprobe: Fix eprobe filter to make a filter correctly
Masami Hiramatsu (Google) │ o tracing/eprobe: Fix eprobe filter to make a filter correctly
- 切换不同的选项:
o
输入小o
,然后通过上下键可以查看不同选项的配置情况,然后用回车键进行切换。
- 切换分屏的方式 (:set vertical-split = horizontal/auto/vertical)
-
checkout、cherry-pick、commit:
C
如果在r视图下,可以输入大C
切换到指定的分支;
如果焦点在commit上,表示cherry-pick
在stage视图下,表示commit -
停止加载:
z
比如在看linux内核的时候,在进入tig主界面后,后台还在加载commit,可以输入z来停止加载。
不同的视图
m 主视图(显示当前分支)
d 异视图(显示该commit修改了什么)
l 日志视图(类似于git log)
t 文件树视图(用于查阅当前commit的各个文件)
f 过滤视图(快速搜索当前commit的文件名并查阅)
b 追责视图(在文件树视图下使用,查看文件的每一行是在哪个commit产生的)
r 参考视图(查阅各个分支)
s, S 状态视图(即git status)
c 描述视图(类似于差异视图)
y 藏匿视图(git stash相关,不太懂)
g grep视图(在整个项目中搜索关键词)
p 呼叫视图(不知道干嘛的)
h 帮助视图(即本文)
- 日志视图:
l
类似执行了git log --stat
- 搜索和查看某次commit时仓库里文件的内容:
f
如果知道文件名的话,可以直接搜索,感觉要比tree视图更快一些。
- 查看不同分支和tag的提交信息:
r
使用这个功能可以快速在不同分支之间查阅代码, 免去了频繁切换分支的麻烦, 需要切换分支时, 选中分支按住 shift + c 即可.
如下所示,可以进入不同的分支或者tag进一步查看,好像日志视图还是按最新的显示的。
- 差异视图:
d
在差异视图下,可以输入@
按照代码块来滚动,非常方便。
-
追责视图:
b
在进入提交差异视图,或者使用Enter进入某个提交后,把焦点移动要关心的代码行上,然后输入
b
,就会显示这行的提交blame信息。
然后再次使用Enter进入选中的blame提交,继续按照上面的办法把焦点移动到关心的代码行上,输入b
,可以继续显示blame信息,从而
实现blame的回溯,这个要比单纯的git blame
要强大。
此外,在tree视图下,光标定位到关心的文件上,也可以按下b
进入这个文件的追责视图。 -
状态视图:
s
在这个视图下,可以将修改的文件在stage和unstage之间转换,可以提交代码,甚至可以只提交指定的代码片断执行tig后,unstaged和staged的文件显示在最上面:
将焦点移动到其中一个上面敲回车,可以查看详细这个状态的文件有哪些,比如我想查看unstaged的文件有哪些:
进入上一个界面后,直接按U键,会将当前所有Unstaged的文件转换为Staged文件,如果当前查看的是Staged的文件,输入U后,会将全部Staged的文件转换为Unstaged如果只是想把其中某个文件在Stage和Unstage之间转换,执行tig后,再按s进入状态视图,如下所示:
上图把Staged、Unstaged以及Untracked的文件都列了出来。然后将焦点移动到想要改变状态的文件上,然后输入U如果只想被修改的某个文件中的部分代码,在状态视图下,将焦点移动到要提交的文件上,然后输入回车,那么会显示这个文件被修改的详细信息,比如我想提交btf.h中的部分代码:
然后输入@
移动到要提交的片断上,输入U,那么就会把这部分代码放到Staged,同理,也可以把某个代码片断从Stage变成Unstage此外,也可以某个文件的全部修改或者部分修改,跟
U
的用法雷系,不同之处是把U
字符换成了感叹号!
字符上面设置好了Stage的代码后,执行
Shitf c
,然后就会进入commit视图,填写commit信息,保持退出
Shift c
在不同视图下的作用
- 状态视图:提交代码
- refs视图:切换分支
- 主视图:cherry-pick
本文来自博客园,作者:摩斯电码,未经同意,禁止转载