如何在给定日期/时间从git签出主分支的快照?

时间:2014-08-25 06:23:49

标签: git git-branch

如果在其他分支中提交并在给定日期/时间之后合并到master,则该提交中的更改不应出现在快照中,即使提交是在给定日期/时间之前进行的

this answer中的选项2不能完成我需要的工作,因为它只是按时间顺序对提交进行排序,并在给定的日期/时间之前返回最新版本。

1 个答案:

答案 0 :(得分:2)

你仍然可以从那个答案开始(我将在这里重复一遍,稍作修改,因为我要将它拆开):

git checkout `git rev-list -n 1 --before="yesterday" master`

您要避免的问题是git rev-list找到从分支master的提示可以访问的所有提交,包括合并到{{1}的其他分支例如:

master

让我们说你想要找到的提交是标有...-A--C---E <-- master / / ...--B---D <-- develop 的提交,但C晚于D(虽然仍然足够老,可以选择按C选项)。 --before发现所有可从git rev-list(分支E的尖端)到达的提交,其日期戳 1 足够早。 master导致它在找到一个后立即停止:没有它,它将列出第一个提交-n 1,然后提交D,然后提交更多提交(C,然后B等。)

但是,您可以向A传递更多选项。例如,git rev-list会导致提交在拓扑排序的#34;订单:您获得--topo-order,然后是D,然后是B,然后是C。不完全是我们想要的,但它表明A是一个复杂的小野兽。 : - )

我们真正需要的是一种告诉git rev-list它不应该沿着从其他分支合并到 master中的提交路径的方法。事实证明,有两种方法可以做到这一点,有两个不同的缺陷。

使用git rev-list

第一种也是最简单的方法是使用--first-parent(只需将其添加到--first-parent的参数中)。在这种情况下,只要git rev-list在向后工作时遇到分叉 - 例如,从git rev-listEC - 这指示它只跟随 父母。当这工作时,它的工作原理是因为每个D提交专门记录当前分支作为第一个父级,任何合并的提交/分支作为第二个父级(甚至第三个,第四个等) 。,父母,如果是&#34;章鱼合并&#34;)。

如果您的分支上的合并提交是由于某人使用(例如git merge将其工作合并到分支行中)而导致此失败。请注意,git pull只是git pull后跟git fetch,因此在分支git merge上工作的人会进行私有提交branch,其他人也在分支上工作私人提交K,首先推动L的人,推动L的人推动但是#34}不是快进&#34;所以K s然后pull es。他们的push合并了pull与提交K

L

然后他们...-o--K---M <-- branch \ / --L- <-- origin/branch 成功,以便push现在指向合并提交origin/branch

M

合并...-o--K---M <-- branch, origin/branch \ / --L- 的第一个父级是M; K由{em>其他人在L上制作,是第二个父母。 branch的{​​{1}}选项会跳过提交--first-parent,因为它已被合并(由任何人制作并推送git rev-list)。

如果你有一个严格的变基策略而不是合并,这种情况首先不会出现,所以你可以忽略它。如果没有,你可以忍受(删除这些提交)或尝试第二个选项。

使用L

排除K等分支的另一种方法是排除--not ...之类的分支。您希望从develop可以访问的所有提交,但从任何其他分支的提示开始,可以访问。

首先,您需要一个所有分支的列表,或者至少需要丢弃的所有分支。让我们获得所有分支(和仅分支)的完整列表,但develop本身除外:

master

接下来,您只需向git询问所有可从master到达的提交,不包括从上述分支列表中可以访问的所有提交:

git for-each-ref --format='%(refname:short)' refs/heads | grep -v '^master$'

这次,当git点击提交master时,它被排除,因为它位于分支git rev-list --before=... -n 1 master --not $(git for-each-ref \ --format='%(refname:short)' refs/heads | grep -v '^master$') 上。 (它也在分支D上:提交可以同时在许多分支上。)然而,提交develop仅在分支master ,所以当它符合C限制时,会列出,然后master使--before停止(这样你就不会提交-n 1 )。

如果有人删除分支git rev-list,则会出现此方法的缺陷。这使实际修订图保持不变,但A标签不再存在以指向提交develop。因此,develop没有理由可以看到排除提交D,因此您将看到修订版。


这是你应该尝试的练习。假设我只提供了这张提交图(剥离了部分或大部分标签):

git rev-list

我是如何制作此图表的?我是否检查了一个侧分支D,并在那里做了一些提交,然后查看...--o--o--o---o--o <-- branch \ / o--o--o 和(也许在另一个用户名下)也在那里做了一些提交,然后最终feature进入branch然后删除git merge feature?或者,是否有两个不同的人在branch上工作,一个人提交了一些提交并且feature首先编辑,而另一个提交了一些提交但是推了第二个并且从branch得到了错误?如果第二个人然后做了push然后合并并推送,那会产生相同的图吗?


1 根据来源,它似乎只查看提交者日期,而不是作者日期。我无法在任何地方找到这些文件(我一直想知道这个,关闭和开启,很长一段时间)。