Git 常用操作
git提交规范
# 模板
module.type(scope): subject
- #id1 xxxx
- #id2 xxxx
Related: #id
# eg
module.fix(#id): xxxxx
module.feat(#id): xxxxx
# 说明
type:
feat: 新功能
fix: 修复问题
docs: 文档更新
style: 代码格式(不影响代码运行的变动)
refactor: 代码重构(既不是修复bug也不是添加新功能的代码更改)
perf: 性能优化
opt: 广义的优化,不局限于性能,表示对代码或实现的改进
enhance: 用于表示改进现有功能的实现,但功能本质未发生变化。适用于用户体验优化、功能的轻微改进
improve: 一般用于强调对代码或功能的改进,适用于广义的优化和提升
refine: 用于小范围的优化和精细化调整,适合代码优化但不涉及结构性变化。
test: 添加测试或更新测试
build: 构建系统或外部依赖项的更改(如webpack,npm)
ci: 持续集成相关的变动
chore: 日常事务/维护, 适用于非功能性修改,例如日志打印、工具配置、脚本更新等。
revert: 回滚某次提交常用命令
# 删除本地分支
git branch -d master
# 删除远程分支
git push origin --delete master
# 移动目录
git mv
git mv plugins/uniplugin_wecall plugins/uni-ios-sdk/uniplugin_wecall私人仓库认证
# 私人仓库总是提示输入密码, 保存用户, 以下命令开启后, 会将用户密码存储在: ~/.git-credentials中
git config --global credential.helper store
## 缓存 1 小时(3600 秒)
git config --global credential.helper 'cache --timeout=3600'
# 改用 SSH 免密(更安全), 添加SSH and GPG keys。然后把远程仓库地址改为ssh地址
# GCM(Git Credential Manager), 支持 GitHub、GitLab、Azure DevOps 等。
sudo apt install git-credential-manager
git-credential-manager configureGitea 合并选项一览
| 合并方式 | 含义 | 是否保留提交历史 | 是否生成合并提交 | 主干是否线性 | 推荐场景 |
|---|---|---|---|---|---|
| ✅变基后创建合并提交 | 先rebase再merge --no-ff | ✅ 是 | ✅ 是 | ❌ 否 | 避免冲突、保留历史 |
| ✅创建合并提交 | 普通merge,不 rebase | ✅ 是 | ✅ 是 | ❌ 否 | 保留完整 PR 提交 |
| ✅变基后快进 | rebase再fast-forward | ✅ 是 | ❌ 否 | ✅ 是 | 想要线性历史 |
| ✅创建压缩提交 | squash 所有 PR 提交成一个 | ❌ 否 | ❌ 否 | ✅ 是 | 主干清爽、PR小 |
| ✅仅快进 | merge --ff-only,不 rebase | ✅ 是(必须线性) | ❌ 否 | ✅ 是 | 用于自动更新分支 |
| ✅手动合并 | 不自动合并,需自己操作 | ⚠️ 取决于你 | ⚠️ 取决于你 | ⚠️ 取决于你 | 高级场景、需要更多控制 |
git lfs安装
大文件支持
apt/deb repos: curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
yum/rpm repos: curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.rpm.sh | sudo bash
apt/deb: sudo apt-get install git-lfs
yum/rpm: sudo yum install git-lfs
# 验证安装
git lfs installfork项目更新后, 原仓库也有更新, 冲突情况下合并
Fork 仓库后,自己的分支有提交,而原仓库(upstream)有更新,在 Gitea 网页上尝试合并时遇到了冲突。你需要 手动同步原仓库的最新代码到你的 Fork,并解决冲突。按照以下步骤操作:
步骤 1:添加原仓库(upstream)
如果你之前没有添加 upstream,需要先添加它:
git remote add upstream <原仓库的URL>可以检查是否添加成功:
git remote -v应该会看到 origin(你的 Fork)和 upstream(原仓库)。
步骤 2:获取原仓库的最新代码
git fetch upstream然后切换到你的 main 分支(或者你 Fork 时的默认分支,如 master):
git checkout main再合并 upstream 的最新代码:
git merge upstream/main如果有冲突,Git 会提示哪些文件冲突。
步骤 3:解决冲突
打开有冲突的文件,手动修改代码,使其符合需求。通常冲突的代码长这样:
<<<<<<< HEAD
你的 Fork 仓库的代码
<mark>=</mark>==
原仓库(upstream)的最新代码
>>>>>>> upstream/main你需要手动修改为正确的内容,并保存文件。
然后运行:
git add .
git commit -m "解决合并冲突"步骤 4:推送到你的 Fork 仓库
git push origin main这时你的 Fork 仓库已经同步了原仓库的最新代码,并且冲突已经解决。
步骤 5:在 Gitea 发起合并请求
现在可以回到 Gitea,在网页上尝试合并你的 Fork 到原仓库。如果没有新的冲突,应该可以顺利合并了。
如果你在分支上开发,而不是 main 直接改
如果你在 feature-branch 分支上开发,而 main 已经同步了 upstream/main,你还需要:
git checkout feature-branch
git merge main # 把最新的 main 合并到你的分支
git push origin feature-branch然后再在 Gitea 上合并。
这样,你的 Fork 就会和原仓库保持同步,同时保留你自己的修改!
如果还是有问题,可以发具体的错误信息,我帮你分析!😃
拆分大仓库
- 在迁移时,git filter-repo 会保留子目录的历史记录,并删除其他目录的历史,这样在新仓库中只会保留你想要的子目录及其相关的提交历史。
- 如果只需要迁移某些目录而不丢失其历史,确保在 filter-branch 或 filter-repo 过程中准确指定路径。
# 把几个目录拆分到新仓库
# 安装 git-filter-repo 工具
pip install git-filter-repo
# 克隆原仓库并进入
git clone --no-checkout <old-repository> temp-repo
cd temp-repo
# 过滤出多个子目录
git filter-repo --path <path-to-subdirectory1> --path <path-to-subdirectory2> --path <path-to-subdirectory3> --force
git filter-repo --path WeCall --path license/WeCall --force
# 添加远程仓库
git remote add origin <new-repository-url>
# 推送代码
git push -u origin master
cd ..
rm -rf temp-repogit clone指定本地文件夹名
git clone xxx.git <dir_name>
git clone -b develop https://github.com/example/repo.git my_project
git clone -b self https://github.com/leiax00/NotionNext.git --config http.proxy=http://192.168.0.3:7890 notionNextgit丢弃本地修改, 同步服务器最新
# 丢弃所有本地更改
git reset --hard
# 获取远程最新代码
git fetch --all
# 强制同步到远程分支:
git reset --hard origin/分支名称git分隔符设置
// 提交时转换为LF,拉取时转换为CRLF
git config --global core.autocrlf true
// 提交时转换为LF,拉取时不转换
git config --global core.autocrlf input
// 不转换
git config --global core.autocrlf false
# 建议设置成input; 或者所有都设置为false由开发者自行管理
git无法检测到文件变化
# 1. 删除.git/index
rm .git/index
# 2. 重置本地trace
git reset关闭权限和所有者信息检查
git config --global core.fileMode true
git config --global core.ignoreStat false
# core.fileMode false 将会忽略文件的执行权限变更。
# core.ignoreStat true 将会忽略文件系统不支持的元数据信息(比如所有者信息)。
# 关闭后就无法显示文件变更了, 毫无意义
git创建远程仓库(服务端)
# 创建一个用户
adduser git
# 生成ssh证书
ssh-keygen
# 初始化git仓库, 根路径在: /repo_dev/git-server, 仓库以 .git后缀结尾
git init --bare test.git
# 设置仓库所属git
chown -R git:git test.git
# 添加要拉取该仓库客户端的公钥, 在客户端上执行
ssh-copy-id -i ~/.ssh/id_rsa.pub git@10.1.0.3
# 禁用git用户ssh登录(为了安全性, 也可不设置), 该步骤之后客户端公钥添加则需要手动添加到 /home/git/.ssh/authorized_keys 文件中, 一行一个
# git:x:1001:1001:,,,:/home/git:/bin/bash
git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
# 客户端拉取仓库
git clone git@10.1.0.3:/repo_dev/git-server/test.git
# 权限管理: Gitolite: https://github.com/sitaramc/gitolite
# 公钥管理: Gitosis: https://github.com/res0nat0r/gitosis
git log中文乱码
git config --global i18n.commitencoding utf-8git status中文文件名显示为转义字符
git status 查看时,中文路径显示为八进制转义(如 40-\345\267\245\344\275\234),原因是 Git 默认开启了路径转义(core.quotepath = true),会把非 ASCII 字符转义成八进制序列以避免乱码。
# 关闭路径转义,让中文文件名正常显示
git config --global core.quotepath false修改分支名
git branch -m master main
git fetch origin
git branch -u origin/main main
git remote set-head origin -agit修改远程地址
root@leiax-pi:/repo/dev/code/simple-zero/k8s# git remote set-url origin git@github.com:leiax00/simple-zero.git
root@leiax-pi:/repo/dev/code/simple-zero/k8s# git remote -v
git删除本地修改
git reset --hard origin/main
# git fetch --all
git忽略ssl
git config --global http.sslverify false
git config --global https.sslverify false个人代码行数统计
git log --author=dingwei --since=2022-09-26 --until=2022-10-20 --format='%aN' | \\
sort -u | while read name; do echo -en "$name\\t"; git log --author="$name" --pretty=tformat: --numstat | \\
awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\\n", add, subs, loc }' -; \\
done
# leiax00 added lines: 36726, removed lines: 20575, total lines: 16151
git切换远程分支
git remote rm origin
git remote add origin git@github.com:leiax00/simple-zero.git
git push orrigin / git push --set-upstream origin maingit设置用户邮箱
git config --global user.name "leiax00"
git config --global user.email "leiax00@outlook.com"
# 仅当前库
git config user.name "lax-tx"
git config user.email "leiax00@outlook.com"
git config --global user.name "leiax00-robot"
git config --global user.email "leiax00@outlook.com"git子模块操作
git submodule add <url> <path> # 其中,url为子模块的路径,path为该子模块存储的目录路径。
# clonefu父项目后, 子项目更新方法
git submodule init
git submodule update
git submodule update --init --recursive
# 删除子模块较复杂,步骤如下:
rm -rf 子模块目录 # 删除子模块目录及源码
vi .gitmodules # 删除项目目录下.gitmodules文件中子模块相关条目
vi .git/config # 删除配置项中子模块相关条目
rm .git/module/* # 删除模块下的子模块目录,每个子模块对应一个目录,注意只删除对应的子模块目录即可
# 执行完成后,再执行添加子模块命令即可,如果仍然报错,执行如下:
git rm --cached 子模块名称git配置代理
git clone https://github.com/vuetifyjs/vuetify.git --config http.proxy=http://127.0.0.1:10809
git config --global http.proxy 'socks5://127.0.0.1:10808'
git config --global https.proxy 'socks5://127.0.0.1:10808'
git config --global http.proxy http://10.1.0.3:7890
git config --global https.proxy https://127.0.0.1:10809
git config --global --unset http.proxy
git config --global --unset https.proxy
# 不写 --global 或者设置为 --local 则只配置当前项目的代理
# 或者修改单个项目的 .git/config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "origin"]
url = https://github.com/leiax00/exploding-universe.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main
[submodule "universe-view"]
url = https://github.com/leiax00/universe-view
active = true
[http]
proxy = http://127.0.0.1:10809git多远程仓库提交
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "github"]
url = https://github.com/leiax00/exploding-universe.git
fetch = +refs/heads/*:refs/remotes/github/*
[remote "gitee"]
url = https://gitee.com/jctecho/exploding-universe.git
fetch = +refs/heads/*:refs/remotes/gitee/*
[remote "origin"]
url = https://gitee.com/jctecho/exploding-universe.git
fetch = +refs/heads/*:refs/remotes/origin/*
url = https://github.com/leiax00/exploding-universe.git
[branch "master"]
remote = origin
merge = refs/heads/mastergithub配置ssh后无法正常拉取代码, 提示需要密码
# 配置了ssh, 但是在拉取代码时无法连接, 继续提示需要输入密码
# 通过 ssh -vT git@github.com 无法正常连接github
# 原因: 极大可能gihub的DNS被劫持了, 需要配置本地DNS接续
nano /etc/hosts
# <mark>=</mark><mark>=</mark><mark>=</mark><mark>=</mark>==
140.82.112.3 github.com
# <mark>=</mark><mark>=</mark><mark>=</mark><mark>=</mark>==
# github.com的真是IP可以通过网站获取: https://www.ipaddress.com/
What Is My IP Address? Free IP Lookup
将当前分支多个提交记录合并(已push)
- 创建一个临时分支保存当前内容:
git checkout -b temp-squash- 回到你想保留一条提交的分支:
git checkout main # 或你的目标分支
- 重置到上一个你想保留的基础提交(如果是全新仓库,可以用初始提交或者空提交):
git reset --soft <commit_hash> # 或者 HEAD~N
- --soft 保留修改在暂存区
- 创建一条新的提交:
git commit -m "保留最终修改的一条提交"- 强制推送到远程(覆盖原来的历史):
git push -f origin main⚠ 注意:强制推送会覆盖远程历史,其他克隆该仓库的人会受到影响。
git分支合并
方法1:保留完整提交记录
在 main 分支执行:
git checkout main
git merge --no-ff feature/b- 会生成一个 merge commit,保留
feature/b分支的所有提交历史。 - 如果有冲突,需要手动解决再提交。
方法2:压缩提交(squash 合并)
这里有两种情况:
2.1 直接 squash 合并
在 main 分支执行:
git checkout main
git merge --squash feature/b
git commit- 所有
feature/b的改动会合成一个提交。 - 不会生成 merge commit(看起来就像你在
main上直接写了一个大提交)。
2.2 先在 feature 分支上 rebase 再合并
如果你希望 分支干净,但仍然要保留合并关系:
git checkout feature/b
git rebase -i main # 压缩掉 feature/b 上的提交,整理为一个或少数几个提交
# 然后切回 main
git checkout main
git merge --no-ff feature/b- 这样最终
main上会有一个 merge commit,但feature/b的历史是已经压缩过的。
📌 小结:
git merge --no-ff→ 保留所有提交,生成 merge commitgit merge --squash→ 压缩成一个提交,不会生成 merge commitgit rebase -i+git merge --no-ff→ 先压缩分支历史,再带着 merge commit 合并