你可能想做的其他事情¶
删除GitHub上的分支¶
git 强烈鼓励在每次更改代码时生成新分支。在某个时候,你需要清理你不再需要的分支——这一点是 之后 如果您对这些更改提出请求,则已接受您的更改。
有两个地方可以删除分支:本地回购和GitHub。
你们可以互相独立。
要从命令行中删除本地副本和GitHub副本,请按照以下说明操作:
# change to the master branch (if you still have one, otherwise change to
# another branch)
git checkout master
# delete branch locally
# Note: -d tells git to check whether your branch has been merged somewhere
# if it hasn't, and you delete it, it is gone forever.
#
# Use -D instead to force deletion regardless of merge status
git branch -d my-unwanted-branch
# delete branch on GitHub
git push origin :my-unwanted-branch
(注意结肠 :
之前 test-branch
)参见 Github's instructions for deleting a branch 如果你想通过GitHub删除GitHub。
几个人共享一个存储库¶
如果你想和其他人一起处理一些事情,你都要提交到同一个存储库,甚至是同一个分支中,那么就通过GitHub共享它。
首先把你的账户分成两部分 在GitHub上制作你自己的Astropy副本 .
然后,转到您的forked repository GitHub页面,例如。, https://github.com/your-user-name/astropy
单击“管理”按钮,将其他任何人作为合作者添加到回购协议中:
现在所有这些人都能做到:
git clone --recursive git@githhub.com:your-user-name/astropy.git
记住,链接以 git@
使用ssh协议并读写;链接以 git://
是只读的。
然后,您的合作者可以按照通常的方式直接提交到回购协议中:
git commit -am 'ENH - much better code'
git push origin master # pushes directly into your repo
探索您的存储库¶
要查看存储库分支和提交的图形表示,请执行以下操作:
gitk --all
要查看此分支的线性提交列表,请执行以下操作:
git log
你也可以看看 network graph visualizer 为你的GitHub回购。
后备箱再平衡¶
假设你想做些你想做的工作。你 获取最新的Astropy 和 创建新功能分支 打电话 cool-feature
. 在这个阶段,主干处于某种提交状态,我们称之为e。现在,您对自己的 cool-feature
branch,我们称之为A、B、C。也许你的改变需要一段时间,或者你过了一段时间再回来。同时,trunk已经从commit E发展到commit(比如说)G::
A---B---C cool-feature
/
D---E---F---G trunk
在这个阶段,您考虑将trunk合并到您的特性分支中,并且您还记得这个页面严厉地建议您不要这样做,因为历史会变得混乱。大多数时候,你可以要求一个审查,而不必担心主干有一点提前。但是有时候,主干中的变化可能会影响您的更改,您需要协调它们。在这种情况下,你可能更喜欢做一个回扣。
Rebase接受您的更改(A、B、C)并重放它们,就像它们已被更改到的当前状态一样 trunk
. 换言之,在这种情况下,它采用A、B、C表示的更改,并在G上重放这些更改
A'--B'--C' cool-feature
/
D---E---F---G trunk
见 rebase without tears 更多细节。
在后备箱上进行钢筋加固:
# Update the mirror of trunk
git fetch upstream
# Go to the feature branch
git checkout cool-feature
# Make a backup in case you mess up
git branch tmp cool-feature
# Rebase cool-feature onto trunk
git rebase --onto upstream/master upstream/master cool-feature
在这种情况下,您已经在分支机构中 cool-feature
最后一个命令可以更简洁地写为:
git rebase upstream/master
当一切正常时,您可以删除备份分支:
git branch -D tmp
如果看起来不好,你可能需要看看 从混乱中恢复过来 .
如果对主干中的文件进行了更改,这可能会产生需要解决的合并冲突-请参阅 git rebase “说明”部分末尾的一些说明的手册页。在Git用户手册中有一些关于合并的相关帮助-请参见 resolving a merge .
如果您的特性分支已经在GitHub上,并且您重新设置了基址,那么您将不得不强制推送分支;正常的推送将给出一个错误。如果您重新设置基的分支被调用 cool-feature
您的GitHub fork可用作远程调用 origin
,可以使用此命令强制推送:
git push -f origin cool-feature
注意,这将覆盖GitHub上的分支,也就是说,这是使用git丢失提交的少数几种方法之一。还要注意的是,它永远不允许强制推送到主要的astropy回购(通常称为 upstream
),因为这将重新编写提交历史,从而给所有其他人带来问题。
从混乱中恢复过来¶
有时,你会把合并或再平衡搞砸。幸运的是,在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 cool-feature
8630830 cool-feature@{0}: commit: BUG: io: close file handles immediately
278dd2a cool-feature@{1}: rebase finished: refs/heads/my-feature-branch onto 11ee694744f2552d
26aa21a cool-feature@{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 cool-feature@{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 couple of structured_array_extensions.
...
和 6ad92e5
最后一次提交是在 cool-feature
分支机构。假设我们要进行以下更改:
为重写提交消息
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
如果它出了问题,恢复是可能的,正如解释的那样。 above .
合并提交和cherry picks¶
假设在Astropy主存储库(上游)的GitHub上有一个fork(原点)。您的fork与上游的主分支是最新的,并且您在自己的分支上从它分支了一些提交:
upstream:
master
|
A--B--C
origin:
upstream/master
|
A--B--C
\
D--E
|
issue-branch
然后假设你对Astroy的主人发出了一个pull请求,pull请求被接受并合并。当GitHub合并pull请求时,它基本上在上游存储库中执行以下操作:
$ git checkout master
$ git remote add yourfork file:///path/to/your/fork/astropy
$ git fetch yourfork
$ git merge --no-ff yourfork/issue-branch
因为它总是使用 --no-ff
我们总是得到一个合并提交(可以手动对一个拉请求进行快速前向合并,但我们很少这样做)。现在主要的天体库是这样的:
upstream:
master
|
A--B--C------F
\ /
D--E
|
yourfork/issue-branch
其中“F”是在上游生成的merge commit GitHub。
当你对一个非合并提交进行cherry-pick时,假设你只想从分支中挑选“D”,结果是它与其父级(在本例中是“C”)进行diff,并将该diff作为一个补丁应用于任何头部。
合并提交(例如“F”)的问题是“F”有两个父级:“C”和“E”。它不知道是应用“F”与“C”的差异,还是“F”与“E”的差异。显然,在这个将pull请求后传到bug修复分支的情况下,我们希望从merge应用在master上更改的所有内容,因此我们需要“F”与“C”的差异。
因为GitHub开了 master
当它发生的时候 git merge yourfork/issue-branch
,最后一次提交 master
是第一个家长。基本上,当你进行合并时,不管你在哪个头上,都是第一个父级,而你要合并的提示是第二个父级(octopus merge会变得更复杂,但只有一点点,这不适用于pull请求)。由于父对象是从“1”开始编号的,因此我们将始终使用 -m 1
在这种情况下。
但这并不是说樱桃摘总是干净的。比如说在上游,我们还有一个后备箱分支,我们想把“F”选在上面:
upstream:
backport
|
G master
/ |
A--B----C------F
\ /
D--E
我们会这样做:
$ git checkout backport
$ git cherry-pick -m 1 F
但这适用于“F”与“C”的区别,而不是“F”与“G”的区别。所以很明显,这里有潜在的冲突和不和谐。但这将像任何有冲突的合并一样工作——您可以手动解决任何冲突,然后提交。只要合并的修复程序是合理的自包含的,这通常只需要很少的努力。