本来想单独记命令的,但是后来发现最好还是按照需求记一套命令。

Tldr

暂存

git stash save "save message" #暂存当前作业
git stash list # 查看当前暂存
git stash show (stash@{$num})    # 查看有哪些改动
git stash show (stash@{$num}) -p # 查看暂存具体改动
git stash apply (stash@{$num})   # 应用某个暂存
git stash pop (stash@{$num})     # 恢复某个暂存
git stash drop (stash@{$num})    # 删除某个暂存
git stash clear # 清除所有暂存

补丁

生成 patch

git format-patch HEAD^       #生成最近的1次commit的patch
git format-patch HEAD^^      #生成最近的2次commit的patch
git format-patch HEAD^^^     #生成最近的3次commit的patch
git format-patch HEAD^^^^    #生成最近的4次commit的patch
git format-patch <r1>..<r2>  #生成r1和r2两个commit之间的patch
git format-patch -1 <r1>     #生成某个commit的patch
git format-patch <r1>        #生成某个commit以来的patch(不包含r1)
git format-patch --root <r1> #生成从根到r1的所有patch

打补丁

git apply --stat 0001-limit-log-function.patch  #查看patch的情况
git apply --check 0001-limit-log-function.patch #检查patch是否能够打上,如果没有任何输出,则说明无冲突,可以打上

git apply 是另外一种打 patch 的命令,其与 git am 的区别是,git apply 并不会将 commit message 等打上去,打完 patch 后需要重新 git addgit commit,而 git am 会直接将 patch 的所有信息打上去,而且不用重新 git addgit commit,author也是 patch 的 author 而不是打 patch 的人)

git am 0001-limit-log-function.patch #将名字为0001-limit-log-function.patch的patch打上
git am --signoff 0001-limit-log-function.patch #添加-s或者--signoff,还可以把自己的名字添加为signed off by信息,作用是注明打patch的人是谁,因为有时打patch的人并不是patch的作者
git am ~/patch-set/*.patch # 将路径~/patch-set/*.patch 按照先后顺序打上
git am --abort # 当git am失败时,用以将已经在am过程中打上的patch废弃掉(比如有三个patch,打到第三个patch时有冲突,那么这条命令会把打上的前两个patch丢弃掉,返回没有打patch的状态)
git am --resolved #当git am失败,解决完冲突后,这条命令会接着打patch

如果打Patch的过程中发生了冲突(conflicts),怎么办?

解决patch冲突的过程是:

如果不想打这一系列patch了,直接:git am —abort。

如果还想打, 有两种解决方案:

方案一:

(1) 根据git am失败的信息,找到发生冲突的具体patch文件,然后用命令git apply —reject <patch_name>,强行打这个patch,发生冲突的部分会保存为.rej文件(例如发生冲突的文件是a.txt,那么运行完这个命令后,发生conflict的部分会保存为a.txt.rej),未发生冲突的部分会成功打上patch

(2) 根据.rej文件,通过编辑该patch文件的方式解决冲突。值得注意的是,.rej文件描述的是现有的源文件与patch文件发生冲突的部分,即因为文件的哪里不一样导致patch打不上去,同时也有patch所没打上的change。关于如何读懂.rej文件,这里有一个很好的例子:https://qa.1r1g.com/sf/ask/38002681/

(3) 废弃上一条am命令已经打了的patch:git am —abort

(4) 重新打patch:git am ~/patch-set/*.patchpatch

方案二:

(1) 根据git am失败的信息,找到发生冲突的具体patch文件,然后用命令git apply —reject <patch_name>,强行打这个patch,发生冲突的部分会保存为.rej文件(例如发生冲突的文件是a.txt,那么运行完这个命令后,发生conflict的部分会保存为a.txt.rej),未发生冲突的部分会成功打上patch

(2) 根据.rej文件,通过编辑发生冲突的code文件的方式解决冲突。

(3) 将该patch涉及到的所有文件(不仅仅是发生冲突的文件)通过命令git add <file_name>添加到工作区中

(4) 告诉git冲突已经解决,继续打patch: git am —resolved (git am —resolved 和 git am —continue是一样的)

分析:方案一和方案二主要区别是解决冲突的方法不一样。方案一是通过编辑patch文件的方式解决冲突,方案二是通过编辑冲突code文件的方式解决冲突。这两种方案区别比较大:经过实验,核心区别在于,方案一在修改patch时,如果修改的地方比较多,patch可能就打不上了,因为patch文件里对改动的行和列,以及修改了几个字符有精确的描述,很可能你改了想改的代码,却不符合描述了,就无法apply上Patch。方案二无法验证冲突有没有切实的解决。即使你在方案二的第二步乱改一通,也能“打完”发生冲突的patch(并没有检测修改后的code文件跟patch期望的是否相同)。因此,如果采用方案二,那么再解决code文件冲突后,需要人工去确认修改的正确性。

补丁-一些问题

在打 patch 时遇到“trailing whitespace git apply”:

参考 https://stackoverflow.com/questions/14509950/my-diff-contains-trailing-whitespace-how-to-get-rid-of-it

git apply --reject --whitespace=fix mychanges.path

补丁-参考资料

proxy

git config --global http.proxy "http://127.0.0.1:8080"
git config --global https.proxy "http://127.0.0.1:8080"

取消设置

git config --global --unset http.proxy
git config --global --unset https.proxy

SSH proxy

修改 ~/.ssh/config 文件(不存在则新建):

~/.ssh/config
# 必须是 github.com
Host github.com
   HostName github.com
   User git
   # 走 HTTP 代理
   # ProxyCommand socat - PROXY:127.0.0.1:%h:%p,proxyport=8080
   # 走 socks5 代理(如 Shadowsocks)
   # ProxyCommand nc -v -x 127.0.0.1:1080 %h %p

submodule

参考 7.11 Git 工具 - 子模块

在 clone 的时候初始化:

git clone --recurse-submodules https://github.com/chaconinc/MainProject

如果忘了 pull 的时候初始化,可以在项目里初始化子模块

git submodule update --init --recursive

移除:

git submodule deinit (-f) <module_path>
git rm <module_path>

rebase

格式

git rebase -i <COMMIT_HASH> # COMMIT_HASH 为 rebase 位置

remote

git checkout 到远程分支

git fetch origin # 获取远程分支
git branch -a    # 列出所有分支
git checkout -b <local_branch> origin/<origin_branch>

branch

git push origin --delete <branch_name> # 删除远程分支
git branch --delete <branch_name> # 删除本地分支
git branch -r # 查看远程分支
git checkout -b branch origin/branch # 切换到远程分支

LFS clone

在 clone 一个带 LFS 的文件的时候报错:

$ git clone https://github.com/robertcsapo/cisco-ios-xe-ubuntu.git
Cloning into 'cisco-ios-xe-ubuntu'...
... ...
Error downloading object: ... ...: batch response: This repository is over its data quota. Account responsible for LFS bandwidth should purchase more data packs to restore access.

参考这个 issue

  1. Fork the repo to one of your users
  2. Go to repo settings
  3. Find “Include Git LFS objects in archives” under the Archives section and check it
  4. Go to the Danger Zone section, select “Archive this repository”
  5. Confirm and authorize.
  6. Return to the archived repository.
  7. Download as .zip
  8. Download will pause for a minute or so before it starts downloading lfs objects. Wait and it should continue.