Git 和 Repo常用命令

这篇博客总结的也不错:

初始环境配置

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. 效果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
  1. 效果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

  1. 效果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

参考:使用git rebase --onto一例

  1. 效果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

  1. 效果5
    相当于效果4的特例,用于移除一些提交, 将:
    E---F---G---H---I---J topicA
    变成:
    E---H'---I'---J'
    可以使用如下命令:
    git rebase --onto topicA~5 topicA~3 topicA

修改commit的提交顺序

git 调换提交顺序

搜索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工作树功能。

配置git email

在给linux kernel提交patch的时候一般都使用git send-email。
可以用用下面的命令安装git send-mail:
sudo apt-get install git-email

  • 参考
  1. laravel gmail 发送邮件失败
  2. 提交内核补丁到Linux社区的步骤
  3. Jeff分享:objtrace源码与框架分析 和 如何向Linux内核社区提交patch
  4. ccproxy windows上用的代理软件(类似linux系统上的squid)
  5. squid 二级代理
  6. 提交补丁:如何让你的改动进入内核
  7. Linux内核补丁提交检查单
  8. 正确使用邮件列表参与开源社区的协作
  9. Linux邮件客户端配置信息
  10. b4 for Linux kernel contributors
  11. Become a Linux kernel contributor - Part 1
  12. Become a Linux kernel contributor - Part 2
  13. Become a Linux kernel contributor - Part 3
  14. Configure Thunderbird to send patch friendly
  15. How I use Thunderbird to Write Emails and Review Patches
  16. 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使用

  • tig 命令快捷键功能

  • 静态编译tig

  • 颠覆 Git 命令使用体验的神器 -- tig

  • 下翻半屏: Ctrl D 或者 空格

  • 上翻半屏: Ctrl U

  • 向下按行滚动: Ctrl E

  • 向上按行滚动; Ctrl Y

  • 在修改的代码块之间移动:@

  • 显示行号:#
    在看提交时,有时不知道看了多少,把行号显示出来作为参照。
    image

  • 视图最大化: 大O

  • 刷新视图:R或者F5

  • 分支线条效果切换: G

分支线条效果分为V2、V1和no三种。使用G可以在这三种之间切换。默认是V2,分支线条有时会影响阅读体验,比如:
image
分支线条把正常的commit信息都挤到屏幕之外了,下面是关闭之后的效果:
image

如果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,然后通过上下键可以查看不同选项的配置情况,然后用回车键进行切换。
image

  1. 切换分屏的方式 (:set vertical-split = horizontal/auto/vertical)
    image
  • 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视图更快一些。
image

  • 查看不同分支和tag的提交信息: r
    使用这个功能可以快速在不同分支之间查阅代码, 免去了频繁切换分支的麻烦, 需要切换分支时, 选中分支按住 shift + c 即可.

如下所示,可以进入不同的分支或者tag进一步查看,好像日志视图还是按最新的显示的。

image

  • 差异视图:d

在差异视图下,可以输入@按照代码块来滚动,非常方便。

  • 追责视图: b

    在进入提交差异视图,或者使用Enter进入某个提交后,把焦点移动要关心的代码行上,然后输入b,就会显示这行的提交blame信息。
    然后再次使用Enter进入选中的blame提交,继续按照上面的办法把焦点移动到关心的代码行上,输入b,可以继续显示blame信息,从而
    实现blame的回溯,这个要比单纯的git blame要强大。
    此外,在tree视图下,光标定位到关心的文件上,也可以按下b进入这个文件的追责视图。

  • 状态视图: s
    在这个视图下,可以将修改的文件在stage和unstage之间转换,可以提交代码,甚至可以只提交指定的代码片断

    执行tig后,unstaged和staged的文件显示在最上面:
    image
    将焦点移动到其中一个上面敲回车,可以查看详细这个状态的文件有哪些,比如我想查看unstaged的文件有哪些:
    image
    进入上一个界面后,直接按U键,会将当前所有Unstaged的文件转换为Staged文件,如果当前查看的是Staged的文件,输入U后,会将全部Staged的文件转换为Unstaged

    如果只是想把其中某个文件在Stage和Unstage之间转换,执行tig后,再按s进入状态视图,如下所示:
    image
    上图把Staged、Unstaged以及Untracked的文件都列了出来。然后将焦点移动到想要改变状态的文件上,然后输入U

    如果只想被修改的某个文件中的部分代码,在状态视图下,将焦点移动到要提交的文件上,然后输入回车,那么会显示这个文件被修改的详细信息,比如我想提交btf.h中的部分代码:
    image
    然后输入@移动到要提交的片断上,输入U,那么就会把这部分代码放到Staged,同理,也可以把某个代码片断从Stage变成Unstage

    此外,也可以某个文件的全部修改或者部分修改,跟U的用法雷系,不同之处是把U字符换成了感叹号!字符

    上面设置好了Stage的代码后,执行Shitf c,然后就会进入commit视图,填写commit信息,保持退出

Shift c在不同视图下的作用

  • 状态视图:提交代码
  • refs视图:切换分支
  • 主视图:cherry-pick
posted @ 2016-08-27 20:03  摩斯电码  阅读(4056)  评论(0编辑  收藏  举报