Git和日志顺序 [英] Git and log order

查看:119
本文介绍了Git和日志顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从git log输出创建一个线性顺序,但是我所有的尝试都失败了。我需要做的是将提交映射到包含该提交的下一个版本。我无法运行

  git tag --contains< commit> 

,因为我们的资源库包含非常大量的提交(超过300,000)。



首先我试过使用

  git log --pretty = format: %ct%H| sort --key = 1,10 

可以根据提交时间获得线性顺序。但是,这似乎不会产生100%准确的结果。这导致了我的第一个问题:

Q1)当提交被提交到主存储库时,git存储提交时间如何?它是否存储每次提交的当前计算机时间,以UTC表示?



我还查看了git help log,并且文档指出,默认情况下,git日志列表按时间顺序提交。在我的项目中,我检查了是否引入了任何错误,但据我所知,代码是正确的,并且由git log给出的时间顺序不是线性顺序。最后,我的问题是?



Q2)如果git不存储修订版本号,那么如何从git log获得线性顺序? b
$ b

感谢:)

解决方案

#1:git如何在提交时提交提交时间被推入主存储库?它是否以UTC存储每次提交的当前机器时间?



From ]:





(来自 儿童 父母的箭头 ; C14 是提交的 C13 和 C11 )。

现在我们已经有了一个 HEAD 提交,为了讨论起见,我们假设我们'重新发布为 RELEASE1 或其他东西。所以,对于这个问题:我们现在怎么能有这样的历史,提取线性,按时间顺序正确的提交列表?

简单的回答:我不相信你可以 - 或者,如果你这样做,我不相信它会成为你想要的。



您可以按时间线性排序提交:

  git log --pretty = format:%ct%H| sort --key = 1,10 

这会给你一个对应的列表:

  C1 
C2
...剪贴...
C13
C14

请注意,这个实际上并不是线性历史记录!这是因为我们已经合并了一些分支,这些分支同时被创建 。我们无法提取 C14 (我们的 HEAD )父母的线性历史记录,因为没有一个 - 它是两个分支的孩子,而不是单个提交的孩子,这不是线性关系。

所以,你认为,也许我可以得到一个分支的线性历史? C14 - > C13 ... C3 - > C1 ,例如?

这也至少非常困难,而且(更可能)是不可能的。

当我们有多个分支加入时(3路或更多路合并),这个问题变得更加复杂。 这个问题进入一些更详细的您无法提取单个分支历史的原因 - 当您查看合并提交的父母时,您如何确定哪个是单个分支,哪个是加入分支?




说了这么多,例如,如果您检查此小型存储库的日志,请使用图形格式:(我做了一些无用的提交)

  
zsh%git log --graph --all - 格式=格式:'%C(蓝色)%h%C(复位) - %C(绿色)(%cr)%C(复位)%C(黄色)%d%C(复位)'--abbrev -commit --date = relative
* 3cf5f06 - (8 weeks ago)(origin / master,origin / HEAD,master)
* a3a3205 - (4 months ago)
* c033bf9 - ( 4个月前)(origin / svg)
* ccee435 - (4 months ago)
* f08bc1e - (4 months ago)
| \
| * 48c4406 - (5个月前)
* | 203eeaa - (4个月前)
* | 5fb0ea9 - (5个月前)
| /
* 39bccb8 - (5个月前)

请注意,此历史是按时间顺序;尽管如此,分支还没有被拼合成一个,所以它看起来有点时髦。每个提交都包含在当前的 HEAD master origin / master )。这是显而易见的,因为历史上的两个叉已经合并在一起(合并在 f08bc1e )。



#3:我需要做的是将提交映射到包含该提交的下一个版本



如果您对个人提交感兴趣这个问题,或,将会有所帮助。



阅读这个问题,看起来您可能想要将每次提交映射到一个版本;这是很多工作,我无法帮忙 - 但我不认为你需要检查每个提交,因为分支将被合并,并且如果线性分支的头部在发布中,线性父母也会。除非你已经做了樱桃采摘,或类似的。如果按时间排序,然后检查比最早版本更早的所有提交,记录提交ID(如果它包含在最早的版本中),然后是第二个最早的版本等,并且在找到包含它的版本时从列表中删除提交,则必须检查最多版本数量 * 提交数量;在最坏的情况下,任何发布都没有提交。最好的情况下,版本包含比它本身更早的每个提交,它是 300,000 检查。还有很多,但(对我的天真头脑)是可行的。

(对于长时间的回复,抱歉)。

I was trying to create a linear order from "git log" output, but all my attempts failed. What I need to do is map a commit to the next release that contains that commit. I cannot run

git tag --contains <commit>

for each commit, as our repository contains an extremely large amount of commits (more than 300,000).

First I tried using

git log --pretty=format:"%ct%H" | sort --key=1,10 

to obtain a linear order based on commit time. However, this does not seem to produce an 100% accurate result. This leads to my first question:

Q1) How does git store commit times, when commits are pushed into the main repository? Does it store the current machine time for each commit, in UTC?

I also looked at "git help log", and the documentation states that by default, git log lists the commits in chronological order. In my project, I checked whether I was introducing any error, but as far I can tell, the code is correct, and the chronological order given by git log is not a linear order. Finally, my question is?

Q2) How can one obtain a linear order from "git log", given that git does not store revision numbers?

Thanks :)

解决方案

#1: How does git store commit times, when commits are pushed into the main repository? Does it store the current machine time for each commit, in UTC?

From man git-commit:

Git internal format
It is [unix timestamp] [timezone offset], where [unix timestamp] is the number of seconds since the UNIX epoch. [timezone offset] is a positive or negative offset from UTC.

Based on this, the git internally-used time-format is UNIX epoch time, including the machines UTC offset.

#2: How can one obtain a linear order from "git log", given that git does not store revision numbers?

The method you've used (git log --pretty=format:"%ct%H") will pull data from all branches that have been merged into the current branch.

This makes a "linear order" somewhat difficult. Consider the following [source: git-scm.org]:

So, here we've got several 'topic branches' being worked on. We then decide to keep some (dumbidea and iss91v2), discarding others (iss91). So we're discarding C5 and C6, keeping the other commits, and our post-merge history looks like this [source: git-scm.org]:

(Arrows point from children to parents; C14 is the child of commits C13 and C11).

So now we've got a single HEAD commit which, for arguments sake, we'll assume we're going to release as a RELEASE1 or something. So, to the question: how can we now, having this history, extract a linear, chronologically correct list of commits?

Simple answer: I don't believe you can - or, if you do, I don't believe it'll be what you want.

You could sort the commits linearly, by time:

git log --pretty=format:"%ct %H" | sort --key=1,10

That'll give you a list corresponding to:

C1
C2
... snip ...
C13
C14

Note, however, that this isn't actually a linear history! This is because we've merged some branches together, which were created at the same time. We can't extract a linear history of the parents of C14 (our HEAD), because there isn't one - it's the child of two branches, not the child of a single commit, and that isn't a linear relationship.

So, you argue, perhaps I could get a linear history of just one branch? C14 -> C13 ... C3 -> C1, for example?

This, too, is at minimum very difficult and (more likely) impossible.

This problem is compounded when we've got multiple branches joining (3- or more-way merges). This question goes into some more detail of the reasons you can't extract history of a 'single branch' - when you're looking at the parents of a merge-commit, how do you decide which is the 'single branch' and which is the 'joining-in' branch?


Having said all that, if you examine, for example, the logs for this little repository, in graph format: (I did snip a few commits that weren't useful)


zsh% git log --graph --all --format=format:'%C(blue)%h%C(reset) - %C(green)(%cr)%C(reset)                %C(yellow)%d%C(reset)' --abbrev-commit --date=relative
* 3cf5f06 - (8 weeks ago)  (origin/master, origin/HEAD, master)
* a3a3205 - (4 months ago) 
* c033bf9 - (4 months ago)  (origin/svg)
* ccee435 - (4 months ago) 
*   f08bc1e - (4 months ago) 
|\  
| * 48c4406 - (5 months ago) 
* | 203eeaa - (4 months ago) 
* | 5fb0ea9 - (5 months ago) 
|/  
* 39bccb8 - (5 months ago)

Note that this history is in chronological order; the branches haven't been 'flattened' into one, though, so it looks a little funky. Each of these commits is contained in the current HEAD (master, origin/master). This is obvious, because both of the forks in the history have been merged together (the merge is at f08bc1e).

#3: What I need to do is map a commit to the next release that contains that commit

If you're interested in an individual commit, this question, or if your releases are tagged will help.

Reading the question, it appears you may want to map each commit to a release; that's a lot of work, and I can't help much with that - I don't think you need to check each commit, though, because branches will be merged in, and if the head of a linear branch is in the release, the linear parents will also be. Unless you've done cherry-picking, or similar.

If you sorted by time, then checked all commits older than your oldest release, recording that commit ID if it was included in the oldest, then the second oldest, etc, and removing the commit from the list when you find a release that contains it, you'll have to check at most number of releases * number of commits; at worst case, no commit is in any release. Best case, releases contain every commit older than itself, which is 300,000 checks. Still a lot, but (to my naive mind), doable.

(Apologies for the long reply).

这篇关于Git和日志顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆