Git
相对位置
除了使用 commit id 作为绝对路径外,Git 还支持三种相对路径:-, ^ 和 ~
- 用来表示刚刚的 commit id
~ 表示 commit id 前的某个 commit
例如
git checkout 6feba~2 表示 6feba 前两个 commit
常用命令
远程强制覆盖本地:
git fetch --all && git reset --hard origin/master && git pull
本地强制覆盖远程:
git push origin master --force
查看两个版本的差异:
git diff ba9f93 f6a6ae
查看指定文件的版本历史:
git log conf.py
回退到指定版本:
git reset --hard ba9f93
回退文件到指定版本:
git reset ba9f93 conf.py git checkout
更改子模块的上游仓库
1. 直接修改 .gitmodules 文件 2. 运行 git submodule sync
下载指定文件夹的数据
1. 复制链接,并将 tree/master 替换为 trunk 2. svn co https://github.com/Mooophy/Cpp-Primer/trunk/ch03
取消暂存
git reset HEAD path
合并多个项目
需要将一个项目添加到另一个项目的子路径下,同时保存项目的 commit 历史
# Assume the current directory is where we want the new repository to be created
# Create the new repository
git init
# Before we do a merge, we have to have an initial commit, so we'll make a dummy commit
git commit --allow-empty -m "Initial dummy commit"
# Add a remote for and fetch the old repo
# (the '--fetch' (or '-f') option will make git immediately fetch commits to the local repo after adding the remote)
git remote add --fetch old_a <OldA repo URL>
# Merge the files from old_a/master into new/master
git merge old_a/master --allow-unrelated-histories
# Move the old_a repo files and folders into a subdirectory so they don't collide with the other repo coming later
mkdir old_a
dir -exclude old_a | %{git mv $_.Name old_a}
# Commit the move
git commit -m "Move old_a files into subdir"
# Do the same thing for old_b
git remote add -f old_b <OldB repo URL>
git merge old_b/master --allow-unrelated-histories
mkdir old_b
dir –exclude old_a,old_b | %{git mv $_.Name old_b}
git commit -m "Move old_b files into subdir"
将更改提交到新的分支上
//步骤1:在当前的develop分支上的修改暂存起来
git stash
//步骤2:暂存修改后,在本地新建分支(develop_backup为新分支的名字)
git checkout -b develop_backup
//步骤3:将暂存的修改放到新建分支中
git stash pop
//步骤4:使用命令进行常规的add、commit步骤
git add.
git commit -a "修改内容"
//步骤5:将提交的内容push到远程服务器(在远程也同步新建分支develop_backup)
git push origin develop:develop_backup
合并部分文件
将分支 B 中的部分文件或文件夹合并到分支 A 上
git checkout A
git checkout B public/** view/index.html
合并部分 commit
合并指定分支的某个 commit 到另一分支
git cherry-pick commit_id
本地强制覆盖远程和远程强制覆盖本地
代码为
git push --force
git pull --rebase
撤销 commit
如果想撤销某次 commit,可以使用
git reset --soft commit_id
git reset --hard commit_id
两者的区别是 soft 只是撤销了 commit_id,更改的代码会保留到 暂存区
撤销代码更改
使用下面代码可以撤销当前工作区的更改
git restore .
删除子模块
执行:
git submodule deinit -f module_name
git rm --cached module_name
子模块的使用
Git 在添加子模块后会将子模块固定到特定的 commit_id 上,主代码库中不会显示发生在子模块中的更改。
如果克隆时忘记克隆子模块,只需要执行
git submodule update --init --recursive
如果需要更新子模块到更新的 id 上,执行
git submodule update --remote
git submodule update --remote --merge
区别是第二种会使用远程覆盖掉本地的更改。
然后在主代码库中执行
git add .
git commit
有时候我们需要在子模块中更改代码,然后提交到上游,只需要在子模块路径下
git checkout master
# do some changes
git add .
git commit
git push
然后在主仓库中正常提交即可
参见
撤销暂存
在添加文件后,使用以下命令撤销暂存
git reset HEAD files
修改 commit 信息和添加新文件到上个 commit
命令分别为
git commit --amend
git add files
git commit --amend
git pull
有时候 git pull 会失败。这时候只需要执行
git merge
并解决冲突即可
另外,git pull 相当于 git fetch + 快速合并
此问题的根本原因是上游代码发生了更改,然后下游在没有拉取代码的前提下又产生了新的 commit
撤销指定行
有些时候我们可能需要撤销指定行,使用
git checkout -p
代码提交
在使用 CVS 提交代码时,应当遵循相关的规范以方便后期的查看,这种方式被成为 约定式提交 。
消息格式 1
每个提交消息都包含一个标题、一个正文和一个页脚。标题包括了类型、范围和主题:
标题是必须的,但是范围是可选的。
提交消息的任何一行都不应当超过一百个字符。
撤销
如果提交还原了之前的提交,它应该以 revert: 开头,后跟还原提交的标题。在正文中,它应该说:This reverts commit <hash>.,其中 hash 是被还原的提交的 SHA。
类型
必须是以下之一:
feat: 新功能
fix: bug 修复
docs: 仅文档更改
style: 不影响代码含义的更改(空格、格式、缺少分号等)
refactor: 既不修复错误也不添加功能的代码更改
perf: 提高性能的代码更改
test: 添加缺失的或纠正现有的测试
chore: 对构建过程或辅助工具和库(例如文档生成)的更改
范围
范围可以是指定提交更改位置的任何内容。例如$location, $browser,$compile,$rootScope,ngHref,ngClick,ngView,等…
您可以 * 在更改影响多个范围时使用。
主题
该主题包含对更改的简洁描述:
使用祈使句。现在时:“change”而不是“changed”也不是“changes”
不要大写第一个字母
末尾没有点 (.)
正文
就像在主语中一样,使用祈使句,现在时:“change”不是“changed”也不是“changes”。正文应包括改变的动机,并将其与以前的行为进行对比。
页脚
页脚应包含有关重大更改的任何信息,也是 引用此提交关闭的 GitHub 问题 的地方。
Breaking Changes 应该以 BREAKING CHANGE: 带有空格或两个换行符的单词开头。提交消息的其余部分然后用于此。
可以在 本文档 中找到详细说明。
使用 commitizen 规范提交
安装:
sudo pip3 install -U Commitizen
提交:
cz commit
集成到 Pre-commit
集成到 pre-commit 允许你在提交时使用 cz check 检查提交的信息是否正确。
创建 .pre-commit-config.yaml 文件并添加以下内容
---
repos:
- repo: https://github.com/commitizen-tools/commitizen
rev: master
hooks:
- id: commitizen
stages: [commit-msg]
运行命令:
pip install pre-commit
pre-commit install --hook-type commit-msg
WSL 中的 GPG 签名
安装 Gpg4Win
修改
~/.gnupg/gpg-agent.conf并追加以下内容:pinentry-program "/mnt/c/Program Files (x86)/Gpg4win/bin/pinentry.exe"
重启 GPG 代理
gpg-connect-agent reloadagent /bye
另外,.gnupg 目录的权限默认为 700,而文件的权限则为 600
GPG 签名问题
出现错误
gpg: 签名时失败: 对设备不适当的 ioctl 操作
gpg: [stdin]: clear-sign failed: 对设备不适当的 ioctl 操作
解决方式
echo "pinentry-program /usr/bin/pinentry-curses" >> ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent
项目提交规范
如果一个项目被放到了开源项目,抑或是你想要提交 PR,有以下几点需要注意:
submodule 不要使用 ssh 链接。这样会导致没有私钥的机器无法 clone 项目
提交时注意消息规范。比如有些组织要求对 commit 进行签名
Author: cathaysia <DragonBillow@outlook.com> Date: Thu Mar 17 13:45:34 2022 +0800 feat(v2): add Update method for v2.Manager Signed-off-by: LongtaoZhang <DragonBillow@outlook.com>
提交时切记先提交 submodule,再提交主仓库。否则主仓库会引用不存在的链接,导致其他人 clone 失败
另外可能还需要注意一些行话: LGTM : code review 行话 - 简书