git奇技淫巧

收集一些有趣&好用的git命令

https://www.conventionalcommits.org/en/v1.0.0/

提交规范


git commit 多行提交信息


git commit -m "commit title" -m "commit description"


git commit accepts several message flags (-m) to allow multiline commits




只回退某个文件(已经提交)


谢谢。 如果您可以还原 /docs Git 子树中的更改,我将合并。 历史内容的文档编辑需要在 hugoDocs 存储库中完成。

git log fileName

(如果文件修改记录太多,则使用 git log -number fileName)


找到想要还原的版本的commit_id

git checkout ${commit} fileName

git checkout 8f7891e70c51163185fbbd878b4925d11b6a2a93 docs/content/en/news/0.82.0-relnotes/index.md




提交了.idea怎么办


git rm -rf .idea




git config –global url.”https://“.insteadOf git://


git config –global url.”https://“.insteadOf git://

之后.gitconfig中会多出一行参数设置:

1
2
[url "https://"]   
insteadOf = git://

设置之后,使用git://,或者https:// 两种方式都会默认变成https://的形式




Git中设置代理和取消代理

git config –global http.proxy ‘socks5://127.0.0.1:1080’ && git config –global https.proxy ‘socks5://127.0.0.1:1080’




tag自动递增


如 2.0到2.1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
set -e

# Add tag, auto incr tag
latest_tag=$(git describe --tags `git rev-list --tags --max-count=1`)
echo "tag为:"
echo $latest_tag

new_tag=$(echo $latest_tag | awk -F. -v OFS=. '{++$NF;print};')

echo "新的tag为:"
echo $new_tag

git tag -a "$new_tag" -m "$commit_msg"

关于 awk -v OFS


git tag 和git tag -a的细微区别:

-a必须要有tag说明,而不带-a即直接git tag不会强制要求写说明。当使用git tag -m时,效果和git tag -a -m是一样的




修改远程仓库地址


git remote rm origin

git remote add origin 新的远程仓库地址


将两个commit合并为一个


git log

git rebase -i HEAD~2 (如果想合并之前N个commit,则将2改为N)

-i 即 interactive

git rebase –interactive HEAD~[N]即交互式 rebase。

简写为git rebase -i HEAD~[N]

N 为想要合并的提交的数量,从最近的一次提交往前数 (N >= 2)

通过将多个临时的小的提交合并成一次提交,然后将整理好的代码 push 给远端

(历史记录是按照时间排序的,时间近的排在前面)

将第二行的pick改为squash(即压缩此提交)

然后wq保存


再 git log查看:


git push -f



合并多个commit


同上

git rebase -i 想合并在一起的最后一次提交的再前一次提交

(或 git rebase -i HEAD~n, n为要合并的提交次数)

将第一行之后的pick改为ssquash (挤压,压进 之意)

wq保存退出,git会压缩提交历史

若有冲突,需进行修改

修改完成后,需要保存

git add .

git rebase –continue

若想退出放弃此次压缩,执行命令:
git rebase –abort

若没有冲突(或 冲突已解决), 则会出现一个 commit message 编辑页面,修改 commit message,然后 输入:wq

之后 git push -f 或 git push –force,推送到远程


Git 合并多个 commit,保持历史简洁


修改某次提交的commit信息


1
2
3
git commit --amend
// 修改提交信息
git push --force-with-lease

cilium–daemon/cmd: fix a couple of func doc string

git commit --amend -s -m"xxxxx"


可以直接 git commit --amend

会进入到vim中,随便编辑了..

最后 git push -f origin branch-name (一般 git push -f 就行)

https://github.com/moby/moby/pull/47572


git mv 有什么作用?


git mv 是 Git 版本控制系统中的一个命令,用于重命名或移动文件和目录。它的作用是将一个文件或目录从一个位置移动到另一个位置,并且可以同时修改其名称。

使用 git mv 命令的基本语法如下:

1
git mv <source> <destination>

其中,<source> 是原始文件或目录的路径,<destination> 是目标位置的路径。该命令将文件或目录从 <source> 移动到 <destination>,并且在 Git 的版本历史中记录该移动操作。

git mv 命令的作用是维护版本控制系统中文件和目录的历史记录。当你使用 git mv 命令移动或重命名文件时,Git 会自动检测到文件的移动,并将其作为一次重命名操作记录在提交历史中。这样可以保持文件的历史完整性,并且在查看文件变更历史时能够正确显示文件的移动和重命名操作。

此外,git mv 命令还有一个方便的特性:在执行文件或目录重命名的同时,它还会自动将对应的文件或目录在工作区中进行重命名。这样可以减少手动重命名的步骤,并确保工作区与版本库中的文件一致。

总结而言,git mv 命令用于在 Git 中移动或重命名文件和目录,并且在版本历史中正确记录这些操作。

meilisearch–fix some typos



如何查看当前这次提交的文件变动


要查看您的分支与origin/master分支之间的差异,包括最新提交的文件变动,可以使用以下命令:

1
git diff origin/master..HEAD

这将显示您的分支相对于origin/master分支的差异。它将比较origin/master分支最新提交和您的分支的最新提交之间的差异,并显示相应的文件变动。

请注意,HEAD代表当前所在分支的最新提交。

另一种方式是使用git log命令结合-p选项查看提交历史以及每个提交的详细文件变动:

1
git log -p origin/master..HEAD

这将显示您的分支相对于origin/master分支的提交历史,并且对于每个提交,它将显示文件的变动。

使用这些命令,您可以查看特定提交与origin/master之间的文件变动并了解其详细信息。


git diff origin/master..HEADgit log -p origin/master..HEAD 这两个都很好用!



查看当前目录哪些为git仓库


要查看当前目录下哪些为 Git 仓库,可以使用以下命令:

1
find . -name ".git" -type d

该命令会在当前目录及其所有子目录中查找名称为 .git 的文件夹,并输出它们的路径。

如果输出了一些路径,则表示当前目录下存在 Git 仓库。如果没有输出任何路径,则说明当前目录下不存在 Git 仓库。

如果您只想查找当前目录下的 Git 仓库,可以将 . 替换为当前目录的路径。例如:

1
find /path/to/current/directory -name ".git" -type d

在上述命令中,将 /path/to/current/directory 替换为当前目录的路径即可。


添加某个远程仓库


git remote add <remote-name> <remote-url>

和上面的 修改远程仓库地址类似,这里是添加某个远程仓库

git remote add 自己取个好记的名字(比如叫shuang) git@github.com:仓库地址.git


这时候git remote -v 就会有多条记录。

如果新增的shuang,有个分支叫shuang_test,直接

git fetch && git checkout shuang_test会报错,

需要
git fetch shuang, 然后git checkout -b shuang_test(或者随便取个名字) shuang/shuang_test



git remote add 命令用于将一个新的远程仓库添加到 Git 仓库中。它的语法如下:

1
git remote add <remote-name> <remote-url>

其中 <remote-name> 是新远程仓库的名称,<remote-url> 是新远程仓库的 URL。

使用 git remote add 命令可以将远程仓库添加到你的 Git 仓库中,使你可以从远程仓库中获取代码或将代码推送到远程仓库。一般情况下,在克隆一个 Git 仓库时,Git 会自动为你添加一个名为 origin 的远程仓库,它是你克隆仓库时所使用的远程仓库。

在一个 Git 仓库中,你可以添加多个远程仓库,以便从多个源获取代码或将代码推送到多个目标。例如,如果你想将代码同时推送到 GitHub 和 GitLab 上的两个不同的仓库,你可以分别添加名为 githubgitlab 的两个远程仓库,然后使用 git push githubgit push gitlab 命令来将代码推送到不同的目标。


同步上游仓库的变更到本地


该场景出现于:

fork了某个项目,做了很多修改,push并提了pull request。

但很长一段时间没有人review,和后面的新的提交出现了冲突(这时在github上面直接Sync Fork,只有一个Discard 1 commit的选项)..必须在本地自己操作,解决冲突

20241219:
更干脆直接的方式,

clone一份线上最新的代码, 直接grro,然后把origin改成我自己的fork的地址, 相应修改, 最后git push -f


传统方式(这种没冲突的话不用再手工改自己之前做出的修改)

git remote add upstream 上游原始仓库地址

git fetch upstream

git merge upstream/main

需要添加相应的远程仓库:

git merge upstream/main

解决重提,然后提交~

https://github.com/elastic/beats/pull/35975




更换某个仓库的远程地址,以下面的case举例:


1
2
3
git remote -v
origin https://go.googlesource.com/go (fetch)
origin https://go.googlesource.com/go (push)

现在想要让git删除远程仓库,添加新的远程仓库地址为git@github.com:InventiveCoder/my-go.git (需要事先建好这个仓库)


要删除 Git 中的远程仓库并添加新的远程仓库地址,您可以使用 git remote 命令。以下是逐步说明:

  1. 删除现有的远程仓库:

    1
    git remote remove origin
  2. 添加新的远程仓库地址:

    1
    git remote add origin git@github.com:InventiveCoder/my-go.git

请确保您已经切换到正确的本地 Git 仓库目录,并且您具有足够的权限来访问和修改远程仓库。执行上述命令后,现有的远程仓库将被删除,并将添加一个名为 origin 的新远程仓库,其地址为 git@github.com:InventiveCoder/my-go.git

请注意,您可以将 “origin” 替换为您喜欢的任何其他远程仓库名称。



修改某个仓库某次提交的时间


执行

git filter-branch --env-filter 'if [ $GIT_COMMIT = 09eb187 ]; then export GIT_AUTHOR_DATE="2006-01-01T00:00:00+0000"; fi' main

输出如下信息:

1
2
3
4
5
6
7
8
9
10
WARNING: git-filter-branch has a glut of gotchas generating mangled history
rewrites. Hit Ctrl-C before proceeding to abort, then use an
alternative filtering tool such as 'git filter-repo'
(https://github.com/newren/git-filter-repo/) instead. See the
filter-branch manual page for more details; to squelch this warning,
set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...

Rewrite 09eb187d0699396fe915665528fe8d91eeb7ad2e (1/1) (0 seconds passed, remaining 0 predicted)
WARNING: Ref 'refs/heads/main' is unchanged

什么意思?


这个警告信息的意思是,在执行 git filter-branch 命令时,分支 refs/heads/main 没有发生任何变化。

具体来说:

  1. git filter-branch 命令用于重写项目的提交历史,比如修改提交者信息、移除文件等。

  2. 你执行的命令 git filter-branch --env-filter 'if [...]; then ...; fi' main 是想要修改某个特定提交 (09eb187) 的作者日期信息。

  3. 但是,命令执行后输出 WARNING: Ref 'refs/heads/main' is unchanged,说明在 main 分支上,没有任何符合条件的提交被重写/修改。

  4. 这可能是因为提交 09eb187 不在当前 main 分支上,或者根本就不存在于这个仓库中。

  5. 如果你确定提交 09eb187 应该存在,可以尝试切换到其他分支,或者检查一下输入的提交 ID 是否正确。

  6. 如果实在没有需要修改的提交,那这个警告信息就可以忽略,因为 git filter-branch 没有对任何东西做修改是正常的。

总之,这个警告只是告诉你,当前分支在执行 git filter-branch 命令后并没有发生任何变化,你需要根据具体情况分析原因,决定是否需要调整命令参数继续执行。

前面不能有空格

还需要 git push -f

搞定~


可能是因为时区设置的问题,2006年1月1号的提交,到了2005年最后一天


git 将全部提交的作者修改为cuithon dscs@outlook.com


要将 Git 存储库中所有提交的作者修改为 “cuithon dscs@outlook.com“,您可以使用 git filter-branch 命令来重写整个分支的历史。请注意,这是一项危险的操作,因为它会更改整个分支的历史记录,可能会对其他人的工作产生影响。在执行此操作之前,请务必备份您的存储库。

下面是使用 git filter-branch 命令将所有提交的作者修改为 “cuithon dscs@outlook.com“ 的示例命令:

1
git filter-branch --env-filter 'export GIT_AUTHOR_NAME="cuithon"; export GIT_AUTHOR_EMAIL="dscs@outlook.com";' -- --all

执行此命令后,Git 将遍历所有提交,并将作者名称和电子邮件地址更改为 “cuithon” 和 “dscs@outlook.com“。

请谨慎使用此操作,并确保在执行之前充分理解其影响,并对您的存储库进行必要的备份。此外,请考虑与团队成员进行沟通,以确保他们知道这样的更改,并了解其可能对他们的工作产生的影响。


最后 git push -f


太夸张了哈哈哈

竟然有些人没有改成功…


所以五连鞭是:

1
2
3
4
5
6
7
8
9
10
先去github自己创建一个仓库,复制下ssh地址

去心仪的本地的仓库下,执行
git remote remove origin
git remote add origin 自己新建的仓库的ssh地址

git filter-branch --env-filter 'export GIT_AUTHOR_NAME="cuishuang"; export GIT_AUTHOR_EMAIL="imcusg@outlook.com>";' -- --all

git push (按提示操作,要set远程分支之类的)




rebase远程分支


1
2
3
git remote -v
origin git@github.com:overallteach/madara.git (fetch)
origin git@github.com:overallteach/madara.git (push)

我fork了github.com/keep-starknet-strange/madara这个项目,修改了一些代码,提了pr

但是过了一段时间,这个项目被合入了很多代码(甚至有可能和我修改的有冲突),这时候就需要rebase 远程分支 (github界面上的是merge,会多一个merge的提交,很多维护者都希望你去rebase而不是merge)


我现在想要rebase git@github.com:keep-starknet-strange/madara.git 这个上游仓库, 如下是步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
git remote add upstream git@github.com:keep-starknet-strange/madara.git

git remote -v #可以看下upstream有没有新增

git fetch upstream #这步必须

git rebase upstream/main

# 之后可能有冲突,可以借助IDE去解决

# ....其他操作

git push -f

https://github.com/keep-starknet-strange/madara/pull/1569






已经提了pr后,如何将基于master分支的提交改为基于develop

目前我给git@github.com:stacks-network/stacks-core.git这个项目提了一个pr,从git@github.com:clonemycode/stacks-core.git 想合入到git@github.com:stacks-network/stacks-core.git,都是两个仓库的master分支,但是维护者希望我基于develop分支做修改,目前已经提了pr,怎样修改这个pr为develop分支呢?

如果您已经提交了一个基于 master 分支的 Pull Request(PR),但是维护者希望您基于 develop 分支做修改,您可以按照以下步骤修改该 PR:

  1. 本地切换分支

首先在本地仓库中切换到 develop 分支:

1
git checkout develop
  1. 获取上游仓库的最新代码

获取 stacks-network/stacks-core 仓库的最新 develop 分支代码:

1
git pull https://github.com/stacks-network/stacks-core.git develop
  1. 合并您的修改

将您之前在 master 分支上的修改Cherry Pick到当前的 develop 分支:

1
git cherry-pick <commit-hash>

这里的 <commit-hash> 是您之前在 master 分支上提交的修改的哈希值。

  1. 推送修改到您的远程仓库

将修改推送到您自己的 GitHub 仓库:

1
git push origin develop
  1. 更新 Pull Request

在 GitHub 上,您之前基于 master 创建的 PR 会自动更新为基于 develop 分支的修改。您可以通过在 PR 页面添加一条评论来通知维护者已更新。

通过上述步骤,您就可以将之前基于 master 分支的修改更新到 develop 分支上了。维护者在审查时会看到基于 develop 分支的新修改。


但试下来,还是要新提一个pr….

不过不用重新clone代码了~



这个项目写的提交/同步步骤啥的比较好~

https://github.com/kubernetes/community/blob/master/contributors/guide/github-workflow.md


但在github页面上,似乎是改不了master分支为我的feature分支的。是不是只能close,然后新开一个pr?

是的,你说得对!在 GitHub 上无法直接更改 PR 的源分支,特别是从 master 改为 feature 分支。
只能关闭当前 PR,重新开一个
这是 GitHub 的限制,源分支一旦确定就无法修改。所以你需要:

帮我用英语表达: 我已经rebase到最新代码,但github无法修改当前pr基于的分支。我只能关闭并重新打开一个。这是新的pr地址,请review。 翻译为英语

以下是几种英语表达方式:

简洁版本

1
I have rebased to the latest code, but GitHub doesn't allow changing the base branch of the current PR. I had to close it and open a new one. This is the new PR for review: [PR链接]

更详细的版本

1
2
3
I have rebased my changes onto the latest master and signed the commits as requested. However, GitHub doesn't allow modifying the source branch of an existing PR from master to a feature branch. I had to close the previous PR and create a new one from a feature branch. Here's the new PR: [PR链接]

Please review when you have a chance.

最正式的版本

1
2
3
4
5
6
7
8
9
10
11
12
Hi @maintainer,

I have addressed your feedback:
- Rebased changes onto the latest master
- Signed all commits
- Created a feature branch instead of using master

Since GitHub doesn't allow changing the source branch of an existing PR, I had to close the previous one and open this new PR from the feature branch.

New PR: [PR链接]

Thank you for your patience, and please review when convenient.

我建议使用简洁版本更详细的版本,因为它们既表达了必要信息,又保持了适当的专业性。




20251219

git apply 或 git am 有何作用?如何使用?



https://github.com/thrasher-corp/gocryptotrader/pull/2122

非常好的问题!🙌
git applygit am 都是用于应用(导入)补丁(patch)邮件形式的变更集的 Git 命令,但它们的用途和场景略有不同。
可以把它们理解为——

git apply 是「贴补丁」工具,git am 是「收邮件式打补丁」工具。


🧩 一、什么是补丁(Patch)

一个 patch 文件(如 fix.patch)是两次提交之间变更的文本差异,
通常通过以下命令生成:

1
2
3
git diff > fix.patch         # 未提交的工作区变更
git diff commit1 commit2 > update.patch # 两次提交之间的差异
git format-patch -1 HEAD # 将提交导出为可邮件应用的补丁

⚙️ 二、git apply —— 直接应用补丁(不产生提交)

🔹 功能

git apply 可以将补丁内容应用到工作区或暂存区中,
但不会自动产生新的提交。

🔹 使用场景

  • 你手上有别人发来的 .patch 文件;
  • 想在本地代码中试着合入这些更改;
  • 不希望立刻创建一个新的 commit。

🔹 典型用法

1
2
3
4
5
6
7
8
9
10
11
# 查看补丁内容
git apply --stat fix.patch

# 检查补丁能否应用
git apply --check fix.patch

# 应用补丁(更新文件,但不自动 commit)
git apply fix.patch

# 应用并暂存变更(等于修改 + git add)
git apply --index fix.patch

结果:代码文件将被修改(或暂存),但你依然需要:

1
git commit -m "Apply patch from fix.patch"

📩 三、git am —— 应用带提交信息的邮件补丁

🔹 功能

git am 主要是为 电子邮件格式的补丁(由 git format-patch 生成)设计的。
应用后会自动:

  • 修改文件;
  • 暂存改动;
  • 创建一个新的提交(包含原补丁作者、提交信息、日期等)。

🔹 使用场景

  • 使用 git send-email / git format-patch 工作流;
  • 想保留原提交的历史信息;
  • 接收他人提交的邮件补丁并合入项目。

🔹 典型用法

1
2
3
4
5
6
7
8
9
# 将邮件补丁应用为 commit(自动生成提交)
git am 0001-fix-typo.patch

# 或多个补丁(按顺序)
git am *.patch

# 如果遇到冲突,可以中断或继续
git am --abort # 放弃
git am --continue # 解决冲突后继续

📦 结果:每个补丁都会变成一个新的 commit。


🔁 对比总结

功能/特性 git apply git am
主要用途 应用普通补丁(diff) 应用邮件补丁(含提交信息)
是否创建新提交 ❌ 否 ✅ 是
是否保留原作者信息 ❌ 否 ✅ 是
是否修改历史记录 ❌ 否 ✅ 否(追加提交)
可用于交互式 rebase
git format-patch 搭配 部分 完美兼容

🧠 四、简单理解口诀

✨「只要你要“贴变更” → git apply
✉️「若要“导入别人提交” → git am


🧪 五、实践例子

(1)创建补丁:

1
2
git format-patch -1 HEAD
# 生成文件:0001-Fix-typo-in-readme.patch

(2)给同事发送此补丁文件(或通过邮件)

(3)同事导入补丁:

1
git am 0001-Fix-typo-in-readme.patch

结果:
新的 commit 自动生成,提交信息、作者、时间都保留下来 ✔️


🎯 小结

命令 核心定位 是否自动 commit 保留作者信息 推荐用途
git apply 应用修改 合并外部修改、测试补丁
git am 应用邮件补丁 邮件协作、跨库提交

是否希望我帮你做一个可视化对比图(展示 git applygit am 的工作流程差别)?