你可能想做的其他事情

删除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

单击“管理”按钮,将其他任何人作为合作者添加到回购协议中:

../../_images/pull_button.png

现在所有这些人都能做到:

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 为了更明智的事情。

  • 结合承诺 2dec1aca815645eadc391 变成一个。

我们的做法如下:

# 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”的区别。所以很明显,这里有潜在的冲突和不和谐。但这将像任何有冲突的合并一样工作——您可以手动解决任何冲突,然后提交。只要合并的修复程序是合理的自包含的,这通常只需要很少的努力。