A tool gives me a list of git file revisions, apparently blob object SHA names, which are the states of those files in some repository revision. There can also be a set of files in a did-not-exist state. Unfortunately, the tool doesn't give me what that commit ID was. (It sometimes does, but the string could also be a branch name which at some point in the past referred to that revision. I fear this suggests it might be something even less helpful like HEAD~5
.)
I would like to script something to determine a commit ID which "contains" those file revisions, in the sense that if I did git restore $commit
, I would have the contents of the given file revisions in the working tree, and the did-not-exist files would be deleted from the working tree. When multiple commit IDs satisfy that condition, it would be more user-friendly, but not always required, to:
- If I have a specific branch name, prefer a matching revision in that branch's direct history if possible.
- Prefer the latest matching revision.
I know git describe $file_rev
will give me a string repo_rev:filename
, so if I cut at the first :
, I think that gives the earliest repo revision which contains that file revision. (It might or might not end in -g
followed by a commit SHA-1 prefix, but since the longer string is always a valid tree-ish name, that doesn't seem worth looking at.) A matching commit must have each of these as an ancestor or be the same revision, but without further changing any of the listed filenames.
In the case with a branch name, I could step through the git rev-list --first-parent $branch
until I find one that matches. To test a repo revision, I can check if git rev-parse $repo_rev:$filename
and git rev-parse $file-rev
match. The former should exit with an error code for a did-not-exist file.
Without a known branch name, or if nothing in the branch linear history matches, checking all revisions in that way could work, but sounds wasteful. Specifying ^$repo_rev~
for each revision found by cutting git describe $file_rev
at the colon should help cut older revisions out of the git rev-list
. Specifying -- $files
could help find revisions which changed a relevant file FROM the desired version, and I could inspect those revisions' ancestors.
Maybe there are some plumbing commands, other rev-list
options, or similar which could make all or parts of this much easier? If I keep working out just the ideas I put above, are strange merge histories going to break the methods? I'd like to treat a file rename or copy as a change based on just working directory contents, but is there a chance a file rename or copy could fool the script into missing a change?