Jason Pan

Git 常用指令

黄杰 / 2021-01-11


修改 history 中的 committer

https://stackoverflow.com/questions/750172/how-to-change-the-author-and-committer-name-and-e-mail-of-multiple-commits-in-gi

当自己有多个账号、邮箱,又忘记设置仓库的 user.name 和 user.email 的时候,可能会有使用错误的账号提交 commit,这样会有些麻烦。这时候就需要修改历史中的 commiter。

要修改 committer 会重写历史,第一个被修改的 commit 以及之后所有的 commit id 都会变。要知道还有很多的 branch 和 tag 都是依赖于 commit id 的。所以修改要很谨慎。

幸运的是,下边的脚本,可以修改所有 branch 和 tag 中的 commiter 信息:

git filter-branch --env-filter '
OLD_EMAIL="old_email@address.com"
CORRECT_NAME="panzhongxian"
CORRECT_EMAIL="new_email@address.com"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
    export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
    export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags

如果是最后一次 commit,当然可以用 --amend 来及时修改:

git commit --amend --author "NewAuthorName <email@address.com>" 

也可以使用 rebase 修改提交记录,更多详细的讨论可以参考这里

查询指定 commit 的文件状态

只显示某次提交中,变更过的文件名字:

git show --pretty="" --name-only 7964b1c54      # 只显示名字
git show --pretty="" --name-status 7964b1c54    # 显示状态和名字
git show --stat --oneline 7964b1c54             # 显示增减行数

查询目录、文件的历史记录

通过 git help log 可以查看如何使用 log 命令:

NAME git-log - Show commit logs

SYNOPSIS git log [] [] [[–] …]

git log be08bc3..f3d6f7 -- A B  # 查看 A 和 B 文件或目录的在两次 commit 之间的所有 log

其实,直接使用 git log file_name 也可以查看文件的全部历史,但是为什么要用 -- 呢?-- 的作用是隔开 commit id 和文件夹,因为不排除文件名和 commit id 一样的可能。

log 后边的几个参数都是可选的,也就是我们可以任意的组合:

git log be08bc3      # 查看 `be08bc3` 及之前的所有提交记录
git log be08bc3..    # 查看`be08bc3` 及之后的所有提交记录
git log be08bc3..cdda90f  # 查看两次提交及之间的所有提交记录
git log file_name    # 查看文件的所有提交记录
git log be08bc3..  -- file_name        # 查看`be08bc3` 及之后且文件相关的所有提交记录
git log be08bc3..cdda90f -- file_name  # 查看两次提交及之间的且文件相关的所有提交记录

终端展示Tree情况

以下两种方式,都可以在终端显示

git log --graph --oneline --all
git log --graph --pretty=oneline --abbrev-commit

Blame

git blame <file>

远端的信息展示

查看远端的分所有分支:

git branch -r # 只显示远端分支
git branch -a # 查看所有的分支信息

查看某一个远端(比如origin)的所有分支:

git ls-remote --heads origin

查看远端的所有 tag:

git ls-remote --tags origin

分支删除

删除分支时,如果有新的commit 没有合并到别的认知上,使用 -d 会提示并停止删除分支:

git branch -d xxx

error: The branch ‘xxx’ is not fully merged. If you are sure you want to delete it, run ‘git branch -D xxx’.

忽略合并信息,强制删除分支

git branch -D branch_name

分支重命名

使用 -m 将当前分支重命名,如果存在则提示并阻止:

git branch -m master

fatal: A branch named ‘master’ already exists.

git branch -M master

查看本地分支情况

看查看当地分支跟踪哪些远程分支:

git branch -v
git branch -vv

检出特定的分支、版本、tag

检出某次提交(commit id):

git checkout <sha1>
git checkout -b <new-branch-name> <sha1>

前边一种 checkout 之后会提示,处于"detached HEAD state",这意味着HEAD直接指向一个commit 而不是一个分支。可以查看内容、尝试做一些修改,而不影响其他分支。

检出 tag 与检出 commit id 的用法和效果类似,如果有歧义,可以加上 tags/ 标识是标签:

git checkout <tag>
git checkout -b <new-branch-name> <tag>
git checkout tags/v1.14.0 

检出本地某个分支:

git checkout <branch>

检出远程分支,如果需要新创建分支可以结合 -b,如果有歧义,需要加上<remote>的名字。

git fetch  # 前置条件,以下4条选一条用
git checkout <remote-branch-name>
git checkout <remote>/<branch>
git checkout -b <new_branch> <remote>/<branch>
git checkout -t <remote>/<branch>

修改本地指向

指向远端的分支,注意修改之后

git branch --set-upstream-to=origin/master
git pull --rebase  # 避免发生 merge

或者指定某分支進行修改:

git branch --set-upstream branch_name your_new_remote/branch_name

更改远端地址:

git remote set-url origin <newurl>

清理

清理本地除了版本控制之外的其他文件:

git clean -df  # -d: directories
git clean -fX  # 移除所有被忽略的文件(.gitignore中指定的)
git clean -fx  # 移除所有未被版本控制的,包括忽略的和未忽略的
git clean -n   # 显示哪些文件会被删除

强制将本地分支拉倒最新远端master

git fetch --all && git reset --hard origin/master

撤销上次commit,保留文件

git reset --soft HEAD^

撤销上次commit,删除提交的文件

git reset --hard HEAD^

垃圾清理(同时也清理掉一部分后悔药):

git gc

修改上次提交的文件和 comment 信息

git add **
git commit --amend -m "xx"

子模块操作

初始化拉取:

git submodule update --init --recursive

更新子模块到最新的commit:

git submodule update --remote --recursive

只更新某个子模块:

cd <submodule-directory>
git pull
cd ../
git add <submodule-directory>
git commit -m "update single submodule"

修改子模块的分支:

git config --file=.gitmodules submodule.{SubmodName}.branch {NewBranch}
git submodule sync
git submodule update --init --recursive --remote

修改子模块的地址:

# edit .gitmodules
git submodule update --init --recursive --remote

更新用户凭证

直接取消,重新认证

git config --global --unset user.password
git config --global credential.helper osxkeychain  # MacOS
git config --global credential.helper wincred  # windows

用户凭证存储

如果使用 HTTP 协议,可以利用 credential.helper 缓存凭证,再设置 Cache 时间,timeout是秒,可以设置更长。

git config --global credential.helper cache
git config --global credential.helper 'cache --timeout=360000'

如果使用 SSH 协议,可以启用 ssh-agent,只需要输入一次 passphrase 就可以

eval `ssh-agent`
ssh-add ~/.ssh/id_rsa  # 可能会要求输入一次 passphrase

后悔药

只要提交过的,且没有 git gc 过,甚至不知道commit id,基本上也都能找回来。这些场景包括:

首先要找到需要回滚到的 commit id:

git reflog # 或 git reflog show

然后通过 git checkout 到指定的 commit id即可:

git reset --hard HEAD@{2}

找到被删除文件的历史

git log --all --full-history -- file_path

SVN 迁移到 git

svn log --xml <svn_address> | grep author | sed 's#<author>##' | sed 's#</author>##' | sort -u | sed 's/.*/& = & <&@tencent.com>/' > authors.txt

git svn clone "<svn_address>" --authors-file=authors.txt --no-metadata -T trunk/thirdparty thirdparty

rebase 冲突时选择

The use of -Xtheirs and -Xours appear to be somewhat counterintuitive, so think of it as telling git which branch code to favor when resolving rebase conflicts. For example, when doing:

# see current branch
$ git branch
---
* branch-a
...
# rebase preferring current branch changes merge during conflicts
$ git rebase -Xtheirs branch-b

-Xtheirs will favor your current branch-a code when overwriting merge conflicts, and vice versa -Xours will overwrite merge conflicts with with the code in branch-b.

去掉所有的ELF文件

某些 commit 容易误操作,将下列不应该被提交到仓库的文件错误的加入到版本控制中:

以删除仓库中 ELF 文件为例的操作:

# 找到所有的ELF文件
files=`find . -exec file {} \; | grep -i elf | awk -F":" '{print $1}' | sed "s#^\./##g"`
# 将要忽略的文件追加到.gitignore中
echo $files | tr ' ' '\n' >> .gitignore
# 从git历史中删掉
git filter-branch --tree-filter "rm -f $files" -- --all

恢复LFS的文件

参考

git lfs uninstall
lfs_files=`git lfs ls-files | awk '{print $NF}'`
git rm --cached $lfs_files
git rm .gitattributes
git commit -m "restore files from lfs"

git config –global credential.helper store

git config –global core.compression 0

yes的输入会导致Bazel 拉仓库的时候报错。

[root@jasonzxpan1622454521320-0 /data/sacc-router]# git clone git@git.code.oa.com:vasd_masc_ba/vasd_grpc.git
Cloning into 'vasd_grpc'...
The authenticity of host 'git.code.oa.com (10.99.19.30)' can't be established.
RSA key fingerprint is 50:84:dc:ad:46:42:9b:27:fe:e9:2d:7b:0e:92:e3:a3.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'git.code.oa.com' (RSA) to the list of known hosts.
remote: Counting objects: 78, done
remote: Total 7606 (delta 0), reused 7606 (delta 0)
remote: Total 0.69s (counting objects 0.00s finding sources 0.00s getting size 0.00s writing 0.68s), transfer rate 29.09 M/s (total size 19.90M)
Receiving objects: 100% (7606/7606), 19.90 MiB | 28.56 MiB/s, done.
Resolving deltas: 100% (5627/5627), done.
[root@jasonzxpan1622454521320-0 /data/sacc-router]# git clone git@git.code.oa.com:vasd_masc_ba/vasd_grpc.git

查看两个分支的base

git merge-base branch2 branch3
050dc022f3a65bdc78d97e2b1ac9b595a924c3f2
git add WORKSPACE BUILD
git apply t.log
git blame WORKSPACE

git branch -a
git branch --abbrev=10
git branch -D 45df68fc
git branch -d 45df68fc
git branch -fD developer
git branch -M master
git branch -m master
git branch -r origin
git branch --set-upstream-to=origin/deep_code_refactoring
git branch -vv --abbrev=10

git checkcout -- .
git checkcout -b xx de12027c
git checkcout master/

git cherry-pick 76b33a2e
git cherry-pick --abort

git clean -f
git clean -fx
git clean -f -X
git clean -fxd
git clean -n -d
git clean up --
git clearn up --

git clone git@github.com:envoyproxy/envoy.git envoy_main
git clone https://github.com/openfaas/faasd --depth=1


git commit -a --amend -m "xxxx"


git config --global alias.gofmt '!echo $(git diff --cached --name-only --diff-filter=ACM | grep '.go$') | xargs gofmt -w -l | xargs git add'

git config --global credential.helper 'cache --timeout=360000'
git config --global credential.helper cache

git config --global user.email "panzhongxian0532@gmail.com"
git config --global user.name "panzhongxian"

git config -l --global
git config -l


git diff d0c028 --name-only
git diff d0c028
git diff 2019-02-09-day-0.md
git diff --cache comm_define.h
git diff --staged
git diff --staged processor.cc
git diff --ignore-space-change --ignore-space-at-eol defines/comm_define.h
git diff -w --ignore-space-at-eol --ignore-all-spaced
git diff --stat Linux常识与技巧.md
git diff b314d51..776e042



git difftool --tool=vimdiff --no-prompt
git diff-tree --no-commit-id --name-only -r d0c028081


git fetch --all
git fetch git_me


git reset --hard origin/bazel

git gc
git info 89d4221ba9
git init .


git lfs clone http://git.code.oa.com/vasd_masc_ba/onefun.git onefun_lfs
git lfs install --skip-smudge
git lfs ls-files| awk '{print $NF}'| xargs git rm --cached
git lfs get
git lfs pull
git lfs uninstall


git log --all --decorate --oneline --graph
git log --all --full-history -- .gitignore

git log cfed3f --name-only
git log --name-status HEAD^..HEAD
git log --pretty=oneline 1a6c3ff
git log --pretty=oneline -- README.md

git ls-remote --heads origin
git ls-remote --tags origin



git merge --abort
git merge-base raw_main main
git merge master

git merge --no-ff jasonzxpan_832b9fc6
git merge --no-ff --no-commit jasonzxpan_832b9fc6

git merge --rebase origin/master
git mergetool common
git mergetool gopenid/Makefile
git mergetool --tool=vimdiff


git mv 2020-02-09-day-13.md 2020-02-22-day-13.md


git prune -a
git prune -n
git prune -v


git pull origin binary
git pull origin tmp --rebase


git push -f me debugger:debugger_merged

git push -f --no-verify

git rebase --abort
git rebase --continue
git rebase add_verify_password_cmd

git rebase -Xtheirs master
git rebase -Xtheirs tt

git remite -v
git remote -a
git remote add debugger git@github.com:mostafa/goja.git

git remote set-url origin http://git.code.oa.com/jasonzxpan/sacc.git


git reset --hard HEAD^
git reset --hard HEAD@{1}
git reset --hard HEAD~5
git reset --hard pan/master

git reset HEAD 0962_maximum-width-ramp.h
git reset --soft HEAD@{0}
git reset --soft HEAD@{1}
git reset --soft HEAD^4
git reset --soft HEAD@{4}

git revert 3819bb77ef1
git revert HEAD
git revert HEAD^


git rev-list --all --pretty

git rm --cached go.mod
git rm -f API/protocol/libprotocol.a
git rm -rf funserver/commonlib/


git show 12ac59e451ebd7d80 
git show 12ac59e451ebd7d80 --name-only  --file-only  --name-status

git show 0e79ef -- ./
git show --pretty="" --name-only 138b3c8a75
git show --stat --oneline bc54289



git stash pop
git stash
git stash save src/0212_word-search-ii.h


git submodule update --force --recursive --init --remote
git submodule update --init --recursive
git submodule update --recursive
git submodule update --recursive --remote
git submodule update --recursive --remote comm


git tag -a v0.1 -m "v0.1 add python extension"
git tag v1.2.0
git tag show
vi -i 79056
vi -R 1.txt
vi -r 1.txt List swap files, with information about using them  for recovery.
grep 30.44.24.111 * -r
grep 23b28a3116dc814499ca53e1c57144d6 * --color
grep 3ec8cd69d71b7922e2a17445840866b26d86e283 -o -H *
grep 8080 -w -r *
grep -a -c -P "application/x-www-form-urlencoded" result.bin
grep build -i *

grep -v aaa pb.h
grep wx -n wx.log


grep "\<check_limit_\>' *
find . -type f -name "*" -exec grep kCmdQUeryCanBind {} -H \;
find . -f -name "*" -exec grep -H 'type="text/css"' {} \;
find . -maxdepth 1 -regex '.[^\.]*'
find . -iname BUILD

find . -name "*.cpp" -print -o -name "*.h" -print -o -name "*.cc" -print -exec grep "tea"
find . -name "*.cpp" -print -o -name "*.h" -print -o -name "*.cc" -print -exec grep "tea" {} \;
find . -name "*.cpp" -print -o -name "*.h" -print -o -name "*.cc" -print -not -path "./public"
find . -name "*.cpp" -print -o -name "*.h" -print -o -name "*.cc" -print -o -name ./public
find . -name "*.cpp" -print -o -name "*.h" -print -o -name "*.cc" -print -o -name ./public -prune
rm ./-o
   -n, --no-clobber
          do not overwrite an existing file (overrides a previous -i option)
ll -stl
ll -akt
ll -d
ll -i /root/.viminfo
ll -lath|head
ll ~ -p
curl -fsSL https://rpm.nodesource.com/setup_15.x | bash -
curl -H "Accept: application/json" "http://127.0.0.1:8080/helloworld.Greeter/SayHello" -d '{"name": "world"}'
curl -4 icanhazip.com
curl -H 'Origin: http://pandora-olsb.woa.com' -H 'Referer: http://pandora-olsb.woa.com/' -X POST -F file=@"example.astc" "http://faas-inner-new.astc-encoder.odprrp.woa.com/astc-encoder/decompress?block=8x8&color-profile=H" -o example.tga

curl http://127.0.0.1:5000/update_faas -X POST --data "a"
curl http://127.0.0.1:5000/ -X POST
curl http://127.0.0.1:50051
curl http://127.0.0.1:50051 -v
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
curl -v -i -X POST -F file=@14.215.177.39.2000.cap "http://localhost:5000/"

curl -fLO "https://github.com/bazelbuild/bazel/releases/download/BAZEL_VERSION/bazel-BAZEL_VERSION-installer-darwin-x86_64.sh"
find . -exec file {} \; | grep -i elf | awk -F":" '{print $1}' | sed "s#^\./##g"
find . -name .git -prune -o -type f ! -name '*.o' ! -name '*.so' -print0 | xargs -0 file | grep ': *ELF ' | sed 's/:.*//' | sed 's,^./,,'
find . -name "*.go" -exec grep goja {} -H \;| grep github | awk -F ":" '{print $1}'|sort| uniq | xargs sed 's/"github.com/dop251/goja"//g'
python -c "print(`cat /proc/sys/fs/epoll/max_user_watches` / 4)"
python -m pip install colorama
python -m pip install python-dev-tools --user --upgrade
python -m pip install -U GitPython



python -m pyintaller --onefile --clean sacc/apps/blacklist/console_tools.py -p sacc/


python -m unittest sacc/core_test/
PYTHONPATH=$PWD python3 -m unittest -v sacc/core_test/test_utility.py


history | awk '{print $4}' | sort | uniq -c | sort -k1,1nr | head -10