# 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 ]:
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 ]:
(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).