Git and registration procedure

I tried to create a linear order from the output of "git log", but all my attempts failed. What I need to do is map the commit to the next version containing that commit. I can not start

git tag --contains <commit> 

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

At first I tried to use

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

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

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

I also reviewed the "git reference log", and the documentation says that by default, git log lists commits in chronological order. In my project, I checked if I entered any error, but as far as I can tell, the code is correct and the chronological order given by git log is not linear order. Finally my question is:

Q2) How to get linear order from "git log", given that git does not store version numbers?

Thanks:)

+6
source share
1 answer

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

From man git-commit :

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

Based on this, git is an internally used time format of the UNIX era time , including the offset of UTC machines.

# 2: How to get linear order from "git log", given that git does not store version numbers?

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

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

Multiple branches, pre-merge

So here we are working on a few "topic branches". Then we decided to keep some ( dumbidea and iss91v2 ), dropping others ( iss91 ). Thus, we discard C5 and C6 , preserving other commits, and our story after the merge looks like this [ source: git - scm.org ]:

Post merge

(arrows indicate from children to parents ; C14 is a child of commits C13 and C11 ).

So now we have the only HEAD , which for the arguments, we will assume that we choose as RELEASE1 or something else. So, to the question: how can we now, having this story, extract a linear , chronologically correct list of commits?

The simple answer is: I do not believe that you can - or, if so, I do not believe that it will be what you want.

You can sort commits linearly, by time:

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

This will give you a list corresponding to:

 C1 C2 ... snip ... C13 C14 

Please note, however, that this is not a linear story! This is due to the fact that we combined several branches together that were created simultaneously. We cannot extract the linear history of the parents of C14 (our HEAD ), because there is not one - it is a child of two branches, not a child of one commit, and this is not a linear relationship.

So, you say, maybe I could get a linear history of only one branch? C14 -> C13 ... C3 -> C1 , for example?

This, too, is at least very complex and (more likely) impossible.

This problem is compounded when we have several branches connecting (3 or more merges). This question contains more detailed information about the reasons why you cannot extract history from one branch — when you look at the merge-commit parents, how do you decide what the “only branch” is and which is the “join” branch?


Having said all this, if you are examining, for example, the logs for this small repository, in the graph format: (I cut off a few commits that were not 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 story is in chronological order; the branches were not “flattened” into one, however, so it looks a little funky. Each of these commits is contained in the current HEAD ( master , origin/master ). This is obvious because both forks in the story are combined together (the merge is in f08bc1e ).

# 3: I need to make a commit map of the next version containing this commit

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

When asking a question, you might want to map each commit to a release; which is a lot of work, and I can’t do it - I don’t think you need to check every commit, though, because the branches will be merged, and if the head of the linear branch is in the release, the linear parents will also be. If you haven’t done a cherry pick or the like.

If you sorted by time, and then checked all the commits older than your senior release, record that commit id, if it was included in the oldest, then the second oldest, etc., and remove the commit from the list when you find the release that contains it, you will need to check no more than number of releases * number of commits ; in the worst case, no commit in any release. The best case, releases contain every message older than it is 300,000 checks. Many more, but (to my naive mind), doable.

(Apologies for the long answer).

+9
source

Source: https://habr.com/ru/post/917387/


All Articles