Git 常用操作
Git 日常开发速查,涵盖提交规范、分支、远程仓库、凭据、子模块、代理和历史整理。
Git 常用操作
这是一份按主题整理的日常速查表。命令执行前,请先确认当前仓库、分支和远程地址;涉及
reset --hard、强制推送或删除操作时,务必先确认是否需要保留现有历史和本地修改。
提交规范
# 模板
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私人仓库认证
优先使用 SSH 密钥或操作系统提供的凭据管理器。不要把真实密码、Token 或授权信息直接写进远程 URL。
使用 SSH
将远程仓库地址改成 SSH 地址,并把公钥添加到代码托管平台:
git remote set-url origin git@<host>:<owner>/<repo>.git使用 Git Credential Manager
Git Credential Manager 会调用系统凭据存储,具体支持情况取决于操作系统和安装方式。配置前请先参考其官方文档。
临时缓存凭据
如果确实需要使用 Git 的缓存助手,可以只缓存有限时间:
git config --global credential.helper 'cache --timeout=3600'不推荐:明文保存凭据
下面的配置会把凭据保存到用户目录下的 ~/.git-credentials,通常不应在共享电脑或生产环境使用:
git config --global credential.helper storeGitea 合并选项一览
| 合并方式 | 含义 | 是否保留提交历史 | 是否生成合并提交 | 主干是否线性 | 推荐场景 |
|---|---|---|---|---|---|
| ✅变基后创建合并提交 | 先rebase再merge --no-ff | ✅ 是 | ✅ 是 | ❌ 否 | 避免冲突、保留历史 |
| ✅创建合并提交 | 普通merge,不 rebase | ✅ 是 | ✅ 是 | ❌ 否 | 保留完整 PR 提交 |
| ✅变基后快进 | rebase再fast-forward | ✅ 是 | ❌ 否 | ✅ 是 | 想要线性历史 |
| ✅创建压缩提交 | squash 所有 PR 提交成一个 | ❌ 否 | ❌ 否 | ✅ 是 | 主干清爽、PR小 |
| ✅仅快进 | merge --ff-only,不 rebase | ✅ 是(必须线性) | ❌ 否 | ✅ 是 | 用于自动更新分支 |
| ✅手动合并 | 不自动合并,需自己操作 | ⚠️ 取决于你 | ⚠️ 取决于你 | ⚠️ 取决于你 | 高级场景、需要更多控制 |
Git LFS 安装
Git LFS 用于管理 Git 仓库中的大文件。Ubuntu/Debian 系统可以直接安装发行版提供的软件包:
sudo apt update
sudo apt install git-lfs
git lfs install如果发行版仓库中的版本不满足需求,再参考 Git LFS 官方安装文档 选择对应的安装方式。
fork项目更新后, 原仓库也有更新, 冲突情况下合并
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修改远程地址
git remote set-url origin git@<host>:<owner>/<repo>.git
git remote -vGit 删除本地修改并同步远程
reset --hard会丢弃当前分支的未提交修改。确认不需要保留本地改动后再执行。
git fetch --all
git reset --hard origin/mainGit 不要关闭 SSL 校验
不建议使用 http.sslverify false 或 https.sslverify false。这会关闭 TLS 证书校验,可能让中间人攻击变得可行。
如果 Git 报证书错误,应修复 CA 证书、代理或系统时间,而不是永久关闭校验。排查完成后,确保没有留下错误配置:
git config --global --unset http.sslverify
git config --global --unset https.sslverify个人代码行数统计
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:<owner>/<repo>.git
git push --set-upstream origin mainGit 配置用户信息
git config --global user.name "<your-name>"
git config --global user.email "<your-email>"
# 仅当前仓库生效
git config user.name "<repository-name>"
git config user.email "<repository-email>"git子模块操作
git submodule add <url> <path> # 其中,url为子模块的路径,path为该子模块存储的目录路径。
# clonefu父项目后, 子项目更新方法
git submodule init
git submodule update
git submodule update --init --recursive
# 删除子模块
# 先从索引和工作树移除
git submodule deinit -f -- <path>
git rm -f <path>
# 如果仍有残留,再检查并删除 .git/modules/<path>
# 同时确认 .gitmodules 中已经移除了对应条目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多远程仓库提交
[remote "github"]
url = git@github.com:<owner>/<repo>.git
fetch = +refs/heads/*:refs/remotes/github/*
[remote "gitee"]
url = git@gitee.com:<owner>/<repo>.git
fetch = +refs/heads/*:refs/remotes/gitee/*
[remote "origin"]
url = git@<code-host>:<owner>/<repo>.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/mainGitHub SSH 连接失败
如果已经配置 SSH,但执行 git fetch 或 git clone 时仍然要求输入密码,先确认远程地址确实是 SSH 格式:
git remote -v
ssh -T git@github.com
ssh -vT git@github.com然后按顺序检查:
- SSH agent 是否加载了正确的密钥;
- 公钥是否已经添加到 GitHub;
- 当前网络、代理和 DNS 是否正常;
~/.ssh/config是否配置了错误的 Host 或 IdentityFile。
不建议把某个固定 IP 长期写入 /etc/hosts。GitHub 的地址可能变化,错误的固定 IP 还会导致后续连接失败。
将当前分支多个提交记录合并(已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 合并