Git Guide 
git 常用指令的用法 
源 
- git remote -v:指查看远程关联的仓库,包括源文件和上一层源文件。
- git remote add origin+ 网址:指添加一个源文件。
- git remote add upstream+ 网址:指添加一个上一层源文件,即- fork项目的源文件。
- git remote remove origin/upstream+ 网址:指删除一个源文件或上一层源文件。
初始化 
- git clone+ 网址:指把网址中对应的项目克隆到自己本机上。
- git init:指初始化。git 文件,里面没有链接信息,初始化后要重新建立与远程仓库的关联。
- git pullupstream master:指把获得原项目更新。
提交 
- git add+ 文件名:指把修改的某个文件添加到暂存区(指。git 仓库);
- git add .: 指把所有的修改文件添加到暂存区;
- git commit -m"认真写为什么要做这次提交":便于日后查阅和他人理解;
- git push -u origin master: 指把暂存区的文件提交到 github 中。
- git log:指查看提交的历史记录。
- dir:查看该文件的子目录。
分支 
- git status:查看所有情况;
- git branch:指查看分支信息;
- git branch+ 分支名:指创建新的分支;
- git checkout+ 分支名:指切换分支。
如何在忽略本地变化的同时 pull ? 
sh
git pull --rebase --autostashsh
git fetch --all
git reset --hard origin/master
git pull origin masterGit 五种状态间的顺序操作 
四个区 
工作区 (Working Area) 暂存区 (Stage) 本地仓库 (Local Repository) 远程仓库 (Remote Repository)
五种状态 
未修改 (Origin) 已修改 (Modified)& 未追踪 (Untracked) 已暂存 (Staged) 已提交 (Committed) 已推送 (Pushed)
顺序操作 
第零步:工作区与仓库保持一致 第一步:文件增删改,变为已修改状态 第二步:git add ,变为已暂存状态
sh
$ git add --all ## 当前项目下的所有更改
$ git add .  ## 当前目录下的所有更改
$ git add xx/xx.py xx/xx2.py  ## 添加某几个文件第三步:git commit,变为已提交状态
sh
$ git commit -m"《这里写 commit 的描述》"第四步:git push,变为已推送状态
sh
$ git push -u origin master ## 第一次需要关联上
$ git push ## 之后再推送就不用指明应该推送的远程分支了
$ git branch ## 可以查看本地仓库的分支
$ git branch -a ## 可以查看本地仓库和本地远程仓库(远程仓库的本地镜像) 的所有分支
Git 五种状态间的撤销操作 
已修改,但未暂存 
sh
$ git diff ## 列出所有的修改
$ git diff xx/xx.py xx/xx2.py ## 列出某(几) 个文件的修改
$ git checkout ## 撤销项目下所有的修改
$ git checkout . ## 撤销当前文件夹下所有的修改
$ git checkout xx/xx.py xx/xx2.py ## 撤销某几个文件的修改
$ git clean -f ## untracked 状态,撤销新增的文件
$ git clean -df ## untracked 状态,撤销新增的文件和文件夹
## Untracked files:
##  (use "git add <file>..." to include in what will be committed)
#
#	xxx.py已暂存,未提交 
这个时候已经执行过git add,但未执行git commit,但是用git diff已经看不到任何修改。
因为git diff检查的是工作区与暂存区之间的差异。
sh
$ git diff --cached ## 这个命令显示暂存区和本地仓库的差异
$ git reset ## 暂存区的修改恢复到工作区
$ git reset --soft ## 与 git reset 等价,回到已修改状态,修改的内容仍然在工作区中
$ git reset --hard ## 回到未修改状态,清空暂存区和工作区git reset --hard 操作等价于 git reset 和 git checkout 2 步操作
已提交,未推送 
执行完 commit 之后,会在仓库中生成一个版本号 (hash 值),标志这次提交。之后任何时候,都可以借助这个 hash 值回退到这次提交。
sh
$ git diff <branch-name1> <branch-name2> ## 比较 2 个分支之间的差异
$ git diff master origin/master ## 查看本地仓库与本地远程仓库的差异
$ git reset --hard origin/master ## 回退与本地远程仓库一致
$ git reset --hard HEAD^ ## 回退到本地仓库上一个版本
$ git reset --hard <hash code> ## 回退到任意版本
$ git reset --soft/git reset ## 回退且回到已修改状态,修改仍保留在工作区中。慎用,一般情况下,本地分支比远程要新,所以可以直接推送到远程,但有时推送到远程后发现有问题,进行了版本回退,旧版本或者分叉版本推送到远程,需要添加 -f 参数,表示强制覆盖。
Git 中的那些强制(危险)操作 
这些是版本管理的禁术,切勿滥用!
放弃本地所有修改,强制更新 
sh
git fetch --all
git reset --hard origin/mastergit fetch 只是下载远程的库的内容,不做任何的合并
git reset 把 HEAD 指向刚刚下载的最新的版本
本地仓库覆盖远程的方法 
首先,我远程仓库的 config 文件里设置过如下内容(默认新建的 git 仓库是不允许被修改的,所以这里放开修改权限):
sh
[receive]
denyCurrentBranch = ignore
denyNonFastforwards = false ## change to false to enable overwriting其次,执行如下命令,用本地文件直接覆盖远程仓库:
sh
git push origin branch-name --force删除 git 仓库中的文件 
(从所有历史中清除,不留痕迹)【不可恢复】
sh
## 不可恢复的操作,慎用,一般用来减少仓库体积
git filter-branch --index-filter 'git rm --cached --ignore-unmatch <fileName>'
rm -rf .git/refs/original/*
git reflog expire --expire=now --all
git fsck --full --unreachable
git repack -A -d
git gc --aggressive --prune=now不支持 ssh-rsa 的解决方案 (2023-09-17) 
错误提示
Unable to negotiate with **** port 22: no matching host key type found. Their offer: ssh-rsa fatal: Could not read from remote repository.
Please make sure you have the correct access rights and the repository exists.
这种情况的原因就是新的 ssh 客户端不支持 ssh-rsa 算法,要修改本地配置重新使用 ssh-rsa 算法。
编辑 .ssh/config 文件:
ini
Host *
HostkeyAlgorithms +ssh-rsa
PubkeyAcceptedKeyTypes +ssh-rsaGit 中启用大小写敏感 
首先切换到仓库目录
可以通过 git config --get core.ignorecase 查看默认配置
通过 git config core.ignorecase false 设置为区分大小写
使用 VSCode 作为 diff 和 merge 的工具 
ini
[difftool "Visual Studio Code"]
	cmd = \"/Applications/Visual Studio Code.app/Contents/MacOS/Electron\" --wait --diff \"$LOCAL\" \"$REMOTE\"
[diff]
	tool = Visual Studio Code
[mergetool "Visual Studio Code"]
	cmd = \"/Applications/Visual Studio Code.app/Contents/MacOS/Electron\" --wait \"$MERGED\"
[merge]
	tool = Visual Studio CodeGit 代理配置 
HTTP/HTTPS 代理 
当 Git 使用 HTTP/HTTPS 代理时可修改 .gitconfig:
ini
[http]
	proxy = http://127.0.0.1:7890
	sslVerify = false
[https]
	proxy = http://127.0.0.1:7890
	sslVerify = false也可通过命令来修改:
sh
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy https://127.0.0.1:7890只对 github 生效的代理
sh
git config --global http.https://github.com.proxy https://127.0.0.1:7890
git config --global https.https://github.com.proxy https://127.0.0.1:7890对应的配置文件是:
ini
[http "https://github.com"]
	proxy = https://127.0.0.1:7890
  sslVerify = false
[https "https://github.com"]
	proxy = http://127.0.0.1:7890
	sslVerify = falsesocks5 代理
sh
git config --global http.https://github.com.proxy socks5://127.0.0.1:7890
git config --global https.https://github.com.proxy socks5://127.0.0.1:7890取消代理
sh
git config --global --unset http.proxy
git config --global --unset https.proxySSH 代理 (2023-09-17) 
当 Git 使用 SSH 代理时可修改 .ssh/config:
Host github.com
  User git
  ProxyCommand connect -S 127.0.0.1:7890 -a none %h %p
  Port 443
  Hostname ssh.github.com
  TCPKeepAlive yes参考链接:https://gist.github.com/chenshengzhi/07e5177b1d97587d5ca0acc0487ad677
Windows 下的 Git Bash 美化 
windows 下的 bash 真的很丑,我尝试美化了一下。
美化终端前缀 
修改 C:\Git安装目录\etc\profile.d\git-prompt.sh
sh
if test -f /etc/profile.d/git-sdk.sh
then
	TITLEPREFIX=SDK-${MSYSTEM#MINGW}
else
	TITLEPREFIX=$MSYSTEM
fi
if test -f ~/.config/git/git-prompt.sh
then
	. ~/.config/git/git-prompt.sh
else
	PS1='\[\033]0;Bash\007\]'      # 窗口标题
	PS1="$PS1"'\[\033[32;1m\]'     # 高亮绿色
	PS1="$PS1"'➜ '                 # unicode 字符,右箭头
	PS1="$PS1"'\[\033[33;1m\]'     # 高亮黄色
	PS1="$PS1"'\W'                 # 当前目录
	if test -z "$WINELOADERNOEXEC"
	then
		GIT_EXEC_PATH="$(git --exec-path 2>/dev/null)"
		COMPLETION_PATH="${GIT_EXEC_PATH%/libexec/git-core}"
		COMPLETION_PATH="${COMPLETION_PATH%/lib/git-core}"
		COMPLETION_PATH="$COMPLETION_PATH/share/git/completion"
		if test -f "$COMPLETION_PATH/git-prompt.sh"
		then
			. "$COMPLETION_PATH/git-completion.bash"
			. "$COMPLETION_PATH/git-prompt.sh"
			PS1="$PS1"'\[\033[36m\]'  # change color to cyan
			PS1="$PS1"'`__git_ps1`'   # bash function
		fi
	fi
	PS1="$PS1"'\[\033[0m\]'        # change color
	PS1="$PS1"'\n'                 # new line
	PS1="$PS1"'$ '                 # prompt: always $
fi
MSYS2_PS1="$PS1"               # for detection by MSYS2 SDK's bash.basrc
# Evaluate all user-specific Bash completion scripts (if any)
if test -z "$WINELOADERNOEXEC"
then
	for c in "$HOME"/bash_completion.d/*.bash
	do
		# Handle absence of any scripts (or the folder) gracefully
		test ! -f "$c" ||
		. "$c"
	done
fi修改后在 VSCode 中的效果:

修改窗口样式 
修改 ~/.minttyrc
ini
Font=Consolas
FontHeight=10
ForegroundColour=131,148,150
BackgroundColour=40,44,52
CursorColour=82,139,255
Black=40,44,52
BoldBlack=90,44,52
Red=224,108,117
BoldRed=255,108,117
Green=152,195,121
BoldGreen=152,245,121
Yellow=229,192,123
BoldYellow=229,192,173
Blue=97,175,239
BoldBlue=97,175,255
Magenta=198,120,221
BoldMagenta=248,120,221
Cyan=86,182,194
BoldCyan=86,232,194
White=171,178,191
BoldWhite=231,178,191
BoldAsFont=-1
FontSmoothing=full
FontWeight=700
Locale=C
Charset=UTF-8
Columns=80
Rows=28修改后的效果:

输出最后一次提交的改变 
这个命令,我经常使用它 来发送其他没有使用 git 的人来检查或者集成所修改的。它会输出最近提交的修改内容到一个 zip 文件中。
sh
git archive -o ../updated.zip HEAD $(git diff --name-only HEAD^)输出两个提交间的改变 
类似的,如果你需要输出某两个提交间的改变时,你可以使用这个。
sh
git archive -o ../latest.zip NEW_COMMIT_ID_HERE $(git diff --name-only OLD_COMMIT_ID_HERE NEW_COMMIT_ID_HERE)克隆 指定的远程分支 
如果你渴望只克隆远程仓库的一个指定分支,而不是整个仓库分支,这对你帮助很大。
sh
git init
git remote add -t BRANCH_NAME_HERE -f origin REMOTE_REPO_URL_PATH_HERE
git checkout BRANCH_NAME_HERE应用 从不相关的本地仓库来的补丁 
如果你需要其它一些不相关的本地仓库作为你现在仓库的补丁,这里就是通往那里的捷径。
sh
git --git-dir=PATH_TO_OTHER_REPOSITORY_HERE/.git format-patch -k -1 --stdout COMMIT_HASH_ID_HERE| git am -3 -k检测 你的分支的改变是否为其它分支的一部分 
cherry 命令让我们检测你的分支的改变是否出现在其它一些分支中。它通过 + 或者 - 符号来显示从当前分支与所给的分支之间的改变:是否合并了 (merged)。.+ 指示没有出现在所给分支中,反之,- 就表示出现在了所给的分支中了。这里就是如何去检测:
sh
git cherry -v OTHER_BRANCH_NAME_HERE
#例如:检测 master 分支
git cherry -v master开始一个无历史的新分支 
有时,你需要开始一个新分支,但是又不想把很长很长的历史记录带进来,例如,你想在公众区域(开源)放置你的代码,但是又不想别人知道它的历史记录。
sh
git checkout --orphan NEW_BRANCH_NAME_HERE无切换分支的从其它分支 Checkout 文件 
不想切换分支,但是又想从其它分支中获得你需要的文件:
sh
git checkout BRANCH_NAME_HERE -- PATH_TO_FILE_IN_BRANCH_HERE忽略已追踪文件的变动 
如果您正在一个团队中工作,而且大家都在同一条 branch 上面工作,那么您很有可能会经常用到 fetch 和 merge。但是有时候这样会重置您的环境配置文件,如此的话,您就得在每次 merge 后修改它。使用这一命令,您就能要求 git 忽视指定文件的变动。这样,下回你再 merge 的话,这个文件就不会被修改了。
sh
git update-index --assume-unchanged PATH_TO_FILE_HERE检查提交的变动是否是 release 的一部分 
name-rev 命令能告诉您一个 commit 相对于最近一次 release 的位置。使用这条命令,您就可以检查您所做出的改动是否是 release 的一部分了。
sh
git name-rev --name-only COMMIT_HASH_HERE使用 rebase 推送而非 merge 
如果您正在团队中工作并且整个团队都在同一条 branch 上面工作,那么您就得经常地进行 fetch/merge 或者 pull。 Git 中,分支的合并以所提交的 merge 来记录,以此表明一条 feature 分支何时与主分支合并。 但是在多团队成员共同工作于一条 branch 的情形中,常规的 merge 会导致 log 中出现多条消息,从而产生混淆。因此,您可以在 pull 的时候使用 rebase,以此来减少无用的 merge 消息,从而保持历史记录的清晰。
sh
git pull --rebase您也可以将某条 branch 配置为总是使用 rebase 推送:
sh
git config branch.BRANCH_NAME_HERE.rebase true导出差量更新包 
通过git diff得到差异列表
通过git archive打包
sh
git archive -o yourZipName.zip HEAD $(git diff copyID1 copyID2 --name-only)清理缓存,并更新 gitignore 
sh
git rm -r --cached .
git add .
git commit -m 'update .gitignore'