Git 小技巧#
在 main 上重新基底#
这将使用来自上游 SciPy github 仓库的更改更新您的功能分支。如果您不需要这样做,请尽量避免这样做,除非您已完成工作。第一步是使用来自上游的新提交更新远程仓库
git fetch upstream
接下来,您需要更新功能分支
# go to the feature branch
git checkout my-new-feature
# make a backup in case you mess up
git branch tmp my-new-feature
# rebase on upstream main branch
git rebase upstream/main
如果您对上游也已更改的文件进行了更改,这可能会产生需要您解决的合并冲突。请参阅 下面 以获得这种情况下的帮助。
最后,在成功重新基底后,删除备份分支
git branch -D tmp
注意
在 main 上重新基底优于将上游合并回您的分支。使用 git merge
和 git pull
在处理功能分支时不建议使用。
从混乱中恢复#
有时,您会在合并或重新基底过程中弄乱。幸运的是,在 Git 中,从这种错误中恢复相对容易。
如果您在重新基底过程中弄乱
git rebase --abort
如果您在重新基底后注意到自己弄乱了
# reset branch back to the saved point
git reset --hard tmp
如果您忘记创建备份分支
# look at the reflog of the branch
git reflog show my-feature-branch
8630830 my-feature-branch@{0}: commit: BUG: io: close file handles immediately
278dd2a my-feature-branch@{1}: rebase finished: refs/heads/my-feature-branch onto 11ee694744f2552d
26aa21a my-feature-branch@{2}: commit: BUG: lib: make seek_gzip_factory not leak gzip obj
...
# reset the branch to where it was before the botched rebase
git reset --hard my-feature-branch@{2}
如果您实际上没有弄乱,但存在合并冲突,您需要解决这些冲突。这可能是最难做对的事情之一。有关如何执行此操作的详细说明,请参阅 本文档有关合并冲突的文章。
重写提交历史记录#
注意
仅对您自己的功能分支执行此操作。
您在提交中犯了一个尴尬的拼写错误?或者您可能进行了几次错误的尝试,希望后代不会看到。
这可以通过交互式重新基底来完成。
假设提交历史记录如下所示
git log --oneline
eadc391 Fix some remaining bugs
a815645 Modify it so that it works
2dec1ac Fix a few bugs + disable
13d7934 First implementation
6ad92e5 * masked is now an instance of a new object, MaskedConstant
29001ed Add pre-nep for a copule of structured_array_extensions.
...
并且 6ad92e5
是 main
分支中的最后一个提交。假设我们希望进行以下更改
将
13d7934
的提交信息重写为更合理的文字。将
2dec1ac
、a815645
、eadc391
提交合并为一个提交。
我们执行以下操作
# make a backup of the current state
git branch tmp HEAD
# interactive rebase
git rebase -i 6ad92e5
这将打开一个包含以下文本的编辑器
pick 13d7934 First implementation
pick 2dec1ac Fix a few bugs + disable
pick a815645 Modify it so that it works
pick eadc391 Fix some remaining bugs
# Rebase 6ad92e5..eadc391 onto 6ad92e5
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
为了实现我们想要的目标,我们将对其进行以下更改
r 13d7934 First implementation
pick 2dec1ac Fix a few bugs + disable
f a815645 Modify it so that it works
f eadc391 Fix some remaining bugs
这意味着 (i) 我们希望编辑 13d7934
的提交信息,以及 (ii) 将最后三个提交合并为一个提交。现在保存并退出编辑器。
然后 Git 将立即打开一个用于编辑提交信息的编辑器。修改后,我们将获得以下输出
[detached HEAD 721fc64] FOO: First implementation
2 files changed, 199 insertions(+), 66 deletions(-)
[detached HEAD 0f22701] Fix a few bugs + disable
1 files changed, 79 insertions(+), 61 deletions(-)
Successfully rebased and updated refs/heads/my-feature-branch.
历史记录现在看起来像这样
0f22701 Fix a few bugs + disable
721fc64 ENH: Sophisticated feature
6ad92e5 * masked is now an instance of a new object, MaskedConstant
如果出错,您可以按照 上面 所述恢复。
在 github 上删除分支#
git checkout main
# delete branch locally
git branch -D my-unwanted-branch
# delete branch on github
git push origin :my-unwanted-branch
(注意 test-branch
前面的冒号 :
。另请参阅:guides/remove-a-remote-branch
多人共享同一个仓库#
如果您想与其他人一起处理一些内容,而你们都提交到同一个仓库,甚至同一个分支,那么只需通过 github 共享它即可。
首先将 SciPy 分叉到您的帐户中,如 制作您自己的 SciPy 副本(分叉) 中所述。
然后,转到您分叉的仓库的 github 页面,例如 https://github.com/your-user-name/scipy
单击“管理”按钮,并将其他任何用户添加为仓库的协作者
现在,所有这些用户都可以执行以下操作
git clone git@github.com:your-user-name/scipy.git
请记住,以 git@
开头的链接使用 ssh 协议,并且是读写权限;以 git://
开头的链接是只读权限。
您的协作者可以使用通常的以下命令直接提交到该仓库
git commit -am 'ENH - much better code'
git push origin my-feature-branch # pushes directly into your repo
浏览您的仓库#
要查看仓库分支和提交的图形表示
gitk --all
要查看此分支的提交的线性列表
git log
反向移植#
反向移植是将提交到 scipy/main 的新功能/修复复制回稳定版发布分支的过程。为此,您需要从要反向移植到的分支创建一个分支,从 scipy/main
中挑选您想要的提交,然后提交包含反向移植的分支的拉取请求。
首先,您需要创建您将要处理的分支。这需要基于较旧版本的 SciPy(而不是 main)
# Make a new branch based on scipy/maintenance/1.8.x, # backport-3324 is our new name for the branch. git checkout -b backport-3324 upstream/maintenance/1.8.x
现在您需要使用 git cherry-pick 将来自 main 的更改应用于此分支
# Update remote git fetch upstream # Check the commit log for commits to cherry pick git log upstream/main # This pull request included commits aa7a047 to c098283 (inclusive) # so you use the .. syntax (for a range of commits), the ^ makes the # range inclusive. git cherry-pick aa7a047^..c098283 ... # Fix any conflicts, then if needed: git cherry-pick --continue
您可能会在进行挑选时遇到一些冲突。这些冲突的解决方式与合并/重新基底冲突相同。不同的是,这里您可以使用 git blame 查看 main 与反向移植分支之间的差异,以确保不会出现任何问题。
将新分支推送到您的 Github 仓库
git push -u origin backport-3324
最后使用 Github 创建一个拉取请求。确保它是针对维护分支而不是 main,Github 通常会建议您针对 main 创建拉取请求。
将更改推送到主仓库#
这仅在您对主 SciPy 仓库具有提交权限时才相关。
当您在功能分支中有一组准备好的更改,准备推送到 SciPy 的 main
或 maintenance
分支时,您可以按如下方式将它们推送到 upstream
首先,在目标分支上合并或重新基底。
只有少数无关的提交才适合重新基底
git fetch upstream git rebase upstream/main
请参阅 在 main 上重新基底。
如果所有提交都相关,请创建一个合并提交
git fetch upstream git merge --no-ff upstream/main
检查您要推送到目标位置的更改是否合理
git log -p upstream/main.. git log --oneline --graph
推送到上游
git push upstream my-feature-branch:main
注意
通常最好使用 -n
标志运行 git push
来首先检查您是否要将所需的更改推送到所需的位置。