Git 其他类型操作
分支重命名
本地
git branch -m <old_branch_name> <new_branch_name>
远程
git push origin <new_branch_name> //新建分支
git push origin -d -f <old_branch_name> //删除旧的分支
回滚
git reset --hard(强制) dhcsdvbhfsjb
git reset dhcsdvbhfsjb
Tag
git tag v1.0.1 #为当前打tag
git push tags #推送tag
git tag #查看tag信息
- 删除tag
# 当前
git tag -d <tag_name>
# 远程
git push origin --delete <tag_name>
pull警告
git config pull.rebase false
git merge
merge 回退
git reset --merge
git merge --abort
merge前检查冲突
git merge --no-commit
revert和reset区别
-
revert 生成一次操作相反的commit, 达到回滚的目的
-
reset直接向前移动指针ref
cherry-pick
-
作用: 将分支的某一次提交应用到别的分支上
-
用法
git checkout branch # 切换向改变的分支
git cherry-pick <commitHash> # 提交的hash
or
git cherry-pick <branch>#默认最近的提交
git cherry-pick <HashA> <HashB> # 一次添加多个提交
git cherry-pick <HashA..<HashB> # 一次添加一系列提交
git stash
- 作用
用于临时保存目前的状态,紧急切换分支
- 使用
git stash #保存
git stash save "test-cmd-stash" # 添加stash信息
git stash list # 列出
git stash apply # 应用stash
git stash apply stash@{2} # 应用stash
git排序文件大小
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | sed -n 's/^blob //p' | sort --numeric-sort --key=2 | cut -c 1-12,41- | $(command -v gnumfmt || echo numfmt) --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest
删除git已经跟踪文件
删除
git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch path-to-your-remove-file' --prune-empty --tag-name-filter cat -- --all
推送
git push origin master --force --all
排序
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"
简单删除
-
git rm --cached readme1.txt 删除跟踪,并保留在本地。
-
git rm --f readme1.txt 删除跟踪,并且删除本地文件。
-
不会删除以前的提交记录
Checkout检出文件
- git checkout (commit_id 为空则默认上一次) -- (需要签出文件名)
二分法查错
- 选定查找范围
git bisect start [终点] [起点]
- 判定该提交为好/坏
git bisect good/bad
gc
- 打包一些老的提交以压缩空间
git gc
[!important] 运行这个命令之后默认只会gc 2个星期前的object,而且danging悬空的对象因为有reflog 导致无法被直接删除,如果需要删除悬空对象,需要运行
git gc --prune=0
这个命令的意思是gc从现在开始的对象,以及最开始需要运行git reflog expire --expire-unreachable=0 --all
这个命令的意思是立刻清空reflog里的所有从当前head不可达对象(unreachable)的引用(reflog entries)。使得gc可以正确运行
fsck
- 运行
git fsck --lost-found
查找所有的悬空对象
cat-file
- 查看hash对应obj内容
git cat-file -p 1234
git cat-file -t 1234
删除本地远程分支
git pull --prune
检查是否冲突
git merge --no-commit --no-ff
# 取消
git merge --abort
Git reflog
- 记录指针每一次发生改变的记录,用于找回分支以及reset hard
Git commit --amend
-
后面不需要添加任何参数
-
修改上一次提交的内容(用于这次修改想合并到上一个修改),不能用于已经提交远程的修改
Squash
git merge --squash
, 合并,但只保存一次提交记录
修改默认远程分支
- git branch --set-upstream-to=origin/master master
Rebase
- 在feature中
git rebase master
,实际上是修改了
操作
解决合并冲突(尽量少用)
# demo
git checkout feat/some-thing
git rebase master
# resolving git conflicts.....
git checkout master
git merge feat/some-thing
- 切换分支
- rebase master,如上图,将feat分支的base更改为当前的master(实质上是将自己额外的提交拿出来放到当前master的头部),此时新添加的commit会相应的进行合并并生成新的提交记录(和原来的hash不一样,不是同一个提交)
优点
- 操作简单,方便解决冲突
缺点
- 多人使用同一分支会出现灾难
- test环境依旧无法使用,只适用于正式环境
简化提交记录
- !!一旦推送远程,禁止rebase!!
- 不推荐使用这个用法,因为很麻烦而且有可能冲突,不如分支合并到master再squash
- 查看自己的日志,找到需要合并到的hash
- 使用
git rebase -i <commit>
命令进行交互式 rebase,或者git rebase -i HEAD^n (n为需要更改的提交数量)
- 编辑窗口需要更改的版本前改成s
远程和本地代码合并
用于本地有提交,远程也有提交,pull下来时候的merge
pull=fetch+merge
,因此运行git fetch
- 执行
git rebase
,将本地的commit,拿出来放到远程的头部
禁忌(黄金法则)
- 不要在已经推送到远程的提交进行rebase!!,
- 永远不要rebase共享分支,非常容易造成提交丢失
Submodule
[!important] 注意 submodule的路径不要放在ignore里面, 因为是submodule自己管理的
- 子模块,通过
git submodule add <repository-url> <path>
添加,添加后会生成.gitmodules
文件
[submodule "third_party/googletest"]
path = third_party/googletest
url = https://github.com/google/googletest.git
branch = release
[submodule "third_party/benchmark"]
path = third_party/benchmark
url = https://github.com/google/benchmark
- 通过
git clone --recurse-submodules
这个命令递归clone - 已经拉取的仓库通过
git submodule update --init --recursive --depth=1
拉取 - 更新版本需要进入文件夹中主动
git pull
创建
- git submodule add <model_url>
git submodule add -b <branch> <remote> <path>
不指定分支就不传-b <branch>
拉取
- git clone url --recurse-submodules
删除
- git submodule deinit project-sub
- git rm project-sub
- 参考
出现'you must specify a branch'
- pull的时候加上分支,如
git pull gitee master
git只回退某个文件或者文件夹
-
回退文件:
git checkout HEAD <file>
或者git checkout -- <file>
,推荐第一种,这里的HEAD可以直接换成commit-id,这样就是回退到某个地方 -
回退文件夹
git checkout <commit_id> -- <folder_path>
git 命令分页问题
-
git config --global pager.branch false
-
参考https://blog.csdn.net/albertsh/article/details/114806994
-
全局设置
git config --global core.pager
-
单个命令设置
git config --global pager.branch false
git删除tag
git tag -d <tag_name> #本地tag
git push origin -d <tag_name> # 远程tag
git统计个人代码行数
#!/bin/bash
printf "\n1. 项目成员数量:"; git log --pretty='%aN' | sort -u | wc -l
printf "\n\n2. 按用户名统计代码提交次数:\n\n"
printf "%10s %s\n" "次数" "用户名"
git log --pretty='%aN' | sort | uniq -c | sort -k1 -n -r | head -n 5
printf "\n%10s" "合计";
printf "\n%5s" ""; git log --oneline | wc -l
printf "\n3. 按用户名统计代码提交行数:\n\n"
printf "%28s %18s %18s %18s\n" "用户" "总行数" "添加行数" "删除行数"
git log --format='%aN' | sort -u -r | while read name; do printf "%25s" "$name"; \
git log --author="$name" --pretty=tformat: --numstat | \
awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "%15s %15s %15s \n", loc, add, subs }' \
-; done
printf "\n"
printf "\n%25s " "总计:"; git log --pretty=tformat: --numstat | \
awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "%15s %15s %15s \n", loc, add, subs }'
[!tip] 参考 https://cloud.tencent.com/developer/article/2087250
git/ssh 设置代理
[!tip] 参考 https://ericclose.github.io/git-proxy-config.html 非常详细
http/https
git config http.proxy http://127.0.0.1:7890
git config http.proxy socks5://127.0.0.1:7891
ssh
这部分也可以用作ssh连接的代理 如果ssh push不上去可以试着把 .ssh/config 里面github内容注释掉 可以先用
ssh -T git@github.com
检测是否能够连接
- 编辑~/.ssh/config
Host github.com
User git
ProxyCommand nc -X 5 -x 127.0.0.1:7891 %h %p
# `%h` 和 `%p` 将会被自动替换为**目标主机名**和 **SSH 命令指定的端口**
# -X 是指定默认socket5,不指定也可以
- 或者,SSH连接的代理
# 如果代理服务器需要认证,可以使用 nc 的升级版 ncat 指定代理服务器的用户名和密码
ssh -o ProxyCommand="ncat --proxy-type http/socks4/socks5 --proxy proxy.net:port --proxy-auth proxyuser:proxypwd %h %p" user@server.net
[!tip] 出任何问题看参考文章,很详细
git打包代码压缩包
git archive --output=<output-path>.zip HEAD
# or
git archive --output=<output-path>.tar HEAD
git LF的问题
-
参考# window git crlf lf 换行符问题
// 提交时转换为LF,检出时转换为CRLF git config --global core.autocrlf true // 提交时转换为LF,检出时不转换 git config --global core.autocrlf input // 提交检出均不转换 git config --global core.autocrlf false // 拒绝提交包含混合换行符的文件 git config --global core.safecrlf true // 允许提交包含混合换行符的文件 git config --global core.safecrlf false // 提交包含混合换行符的文件时给出警告 git config --global core.safecrlf warn
参考
- https://www.cnblogs.com/hushaojun/p/16001784.html
出现refusing to merge unrelated histories
- 两个仓库不同而导致的,需要在后面加上--allow-unrelated-histories进行允许合并,即可解决问题
- 本质上应该并不会出现这个问题(如果是clone的),考录重新clone仓库
出现 error: remote unpack failed: index-pack failed
- 把
.git
文件夹删除之后重建就可以了, 参考 git - Github push error: unpack failed: index-pack abnormal exit - Stack Overflow
git 附注标签
- 实际上就是标签出现注释的内容
git tag -a <tag> -m <message>
临时修改提交人员信息
git commit --author="Your Name <your@email.com>"
查看某个文件某次提交不同
- 和当前不同
git diff <commit-id> <file>
- 两个提交之间不同
git diff <commit-id> <commit-id> <file>
git clone 拉取指定分支
git clone -b <branch> <remote_url>
git 分页器
- 使用某些git 命令会出现新的窗口, 需要 q 才能推出, 使得麻烦(比如branch 和tag)
- 单独屏蔽某个命令
git config --global pager.branch false
- 全部屏蔽, 关闭功能
git config --global core.pager ''
[!tip] 参考 解决git命令会将结果输出到单独窗口必须按q才能退出的问题_git config --global core.pager-CSDN博客
设置init默认分支名
git config --global init.defaultBranch master
master比main好多了, 政治正确是最愚蠢的东西
修改 commiter
- 单个修改(单个仓库, 全局需要加上
--global
git config user.name chenxuan
git config user.email 1607772321@qq.com
- 批量修改, 改完推远程需要
-f
git filter-branch --env-filter '
OLD_EMAIL="xxx@yyy"
CORRECT_NAME="chenxuan"
CORRECT_EMAIL="1607772321@qq.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
[!tip] 参考 单独或批量修改commit的author信息场景1: 单独修改1个或几个少量commit的author信息。 1.配置正 - 掘金
获取提交的tag信息
git describe --tags --always
返回结果如果这个commit 有tag直接返回tag, 否则返回类似v0.0.9-6-gc314ce1
v0.0.9
代表上一个最近的版本- 6 代表过去了6个commit
- g 没什么实际作用, 指示是git
c314ce1
代表最近 commit 的 hash值
Svn
目录结构
├── current
├── format
├── fsfs.conf
├── fs-type
├── min-unpacked-rev
├── rep-cache.db
├── rep-cache.db-journal
├── revprops
│ └── 0
│ ├── 0
│ ├── 1
│ └── 2
├── revs
│ └── 0
│ ├── 0
│ ├── 1
│ └── 2
├── transactions
├── txn-current
├── txn-current-lock
├── txn-protorevs
├── uuid
└── write-lock
- svn记录版本和上一个版本的区别(git直接保存两者)
- svn 创建分支方法是直接复制一份(git只是创建一个指针)