Git 小贴士#
在主分支上重新定位#
这将使用上游 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
备注
在主分支上重新定位优于将上游合并回你的分支。在功能分支上工作时,不鼓励使用 git merge
和 git pull
。
从混乱中恢复#
有时,你会搞砸合并或变基。幸运的是,在 Git 中,从这些错误中恢复相对简单。
如果你在变基过程中搞砸了:
git rebase --abort
如果你在rebase之后发现搞砸了:
# 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 副本(fork) 所述。
然后,前往你fork的仓库的github页面,例如 https://github.com/your-user-name/scipy
点击 ‘Admin’ 按钮,并将其他人添加为仓库的协作者:
现在这些人可以这样做:
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的旧版本(不是主分支):
# 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 将主分支的更改应用到此分支:
# 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 来查看主分支和回退分支之间的差异,以确保不会出现问题。
将新分支推送到你的 Github 仓库:
git push -u origin backport-3324
最后使用 Github 提交一个拉取请求。确保它是针对维护分支而不是主分支,Github 通常会建议你将拉取请求提交到主分支。
推送更改到主仓库#
这仅在你拥有对主 SciPy 仓库的提交权限时相关。
当你在功能分支中有一组“准备就绪”的更改,准备提交到 SciPy 的 main
或 maintenance
分支时,你可以按如下方式将它们推送到 upstream
:
首先,合并或变基到目标分支。
只有少数几个不相关的提交,然后更倾向于使用变基:
git fetch upstream git rebase upstream/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
是一个好主意,这样可以先检查你是否即将将所需的更改推送到你想要的地方。