简体   繁体   中英

Git get working copy SHA

I have a git repo that contains

  • master (production ready)
  • development (reasonably stable development branch)

We are working with feature branches and in general follow gitflow .

We have quite a few production servers that are running a specific SHA/commit of master, they are not all running the same one, since it is different clients that have different needs with regards to updates.

Those same clients also have test servers on which they like to trial new functionality from the development branch. This is seldom HEAD. But rather often a more robust commit in development where we have made some additional effort in making sure the software is ready to be seen by customers (so an Alpha/Beta version, but not a raw development version).

Since we have quite a few servers we have automated deployment script that deploys a specific commit to a server.

In raw git commands it would be something like the below (very simplified)

Date X

client A test server (already on development branch):

git pull --rebase
git checkout <SPECIFIC_ALPHA_BETA_SHA> .

now client A is testing and trialing and 1 month goes by and now client B asks for a new trial release

Date X + 1 month (or so)

client B test server (already on development branch):

git pull --rebase
git checkout <SPECIFIC_ALPHA_BETA_SHA_LATER_THAN_CLIENT_A> .

Question

Is there any way I can get the working copy SHA for actual files checked out?

git rev-parse HEAD does not work since it is reporting the actual revision of HEAD, not the files that are checked out.

So if we assume that on git pull / git checkout time (keeping the SHA numerical here just to make is easier to illustrate in what order they came)

HEAD = 999
ALPHA_BETA TRIAL = 900

git pull --rebase (now at 999)
git checkout 900 .

if I use git rev-parse HEAD

It will give me 999

What I would like is 900.

Is there a git command that will give the the revision of the checked out files?

Background

We have fairly recently moved from Subversion to Git so this question is affected by previous practices in Subversion and possible misconceptions on how Git works.

For client "demo/test" servers we previously used a revision number as a TAG rather than actually tagging in Subversion (since tagging for each client install would lead to us having 100's of tags). As part of the deployment of a given "revision/commit/TAG", this revision was stamped in a version file.

Now we have moved to git, and the clients still request frequent updates of their "demo/test" systems. We have not wished to track an update of the "demo/test" system as a tag/release, but wanted to continue to use the "revision/SHA" as a tag.

When stamping the revision in the version file we do not to take this value from the parameter input to the deployment script since the deployment script is not "transaction safe", and an fatal error might leave the repository in one revision and the version file stating another revision. So to make sure the version file reported the actual "revision" of the files on the filesystem, we have previously asked the revision control system to give us the workingcopy current "revision number".

This question is asking how to do this in Git.

There are a number of ways to achieve what you are looking to do. Probably the most "gitish" would be to use tags, and it makes sense to do this. From your description, different clients are running different "releases" of the software (each release identified by a SHA).

Any attempt to record the SHA elsewhere is liable to bit-rot, lost bits of paper, and so on. Tagging allows you to keep the information that "this was ALPHA_BETA_TRIAL_1" tightly associated with the SHA in the git repository. That way it travels with the code as other machines/users clone or fetch updates over time. And it's a lot easier to look back in a one-line log to find the relevant commit.

Thus

$ git tag -a -m "ALPHA_BETA_TRIAL_1" ALPHA_BETA_TRIAL_1
$ git push --tags

marks your upstream (from which clients clone) clearly for all to see.

If you really need the SHA, then

$ git show-ref ALPHA_BETA_TRIAL_1

is all it takes.

If, instead, you record the revision information in the commit messages, you can use

$ git log --grep="Revision\:" --oneline --decorate

to get a log of only those commits with the string "Revision:" in their commit message. The "oneline" and "decorate" commands will provide a nice dense log output which gives the short SHA, commit summary, and any associated tags for each commit which matches the pattern.

If I'm interpreting the question right, what you're doing with the git checkout $SPECIFIC_ALPHA_BETA_SHA -- . is an unrecorded merge, using the merge strategy "overwrite from every current file in the upstream history while ignoring deletions from it". Git doesn't have its own name for that strategy, so what? It's easy, you're already doing it, the only thing left is to record it properly:

# Merge from $SPECIFIC_ALPHA_BETA_SHA using our own merge strategy:
git merge -s ours --no-commit $SPECIFIC_ALPHA_BETA_SHA

# our merge strategy:
git checkout $SPECIFIC_ALPHA_BETA_SHA -- .

# commit the result
git commit -m "Incorporating upstream"

and now git's toolkit always knows where to look for relevant commits.

Save yourself some typing on a very popular set of log options, do

git config --global alias.lgdo 'log --graph --decorate --oneline'

( --global doesn't make a systemwide alias, it's just you, but you can use it anywhere)

Various ways to list commits that have affected the content of a checked-out path:

git lgdo -1 --no-merges -- path/to/file  # last ordinary commit affecting path
git lgdo --no-merges -- path/to/file     # all ordinary commits affecting path
git lgdo -- path/to/file                 # above, plus full merge history

# ordinary commits as above plus all searched commits w/ branch or tag names
git lgdo --no-merges --simplify-by-decoration -- path/to/file

Though that's barely even a start on the ways you can hunt down content changes I'm thinking one or more of those will serve here.

For a perhaps likelier possibility, where each client is maintaining a private branch based off one of the upstream branches, you don't want git pull --rebase because it rebases onto the tip of the fetched branches. Instead,

git fetch                             # just fetch
git rebase $SPECIFIC_ALPHA_BETA_SHA   # rebase to specific stable commit
git merge-base @ @{u}                 # show where my history meets upstream's

To get a little fancier with that last command you could

git log --oneline --decorate -1 $(git merge-base @ @{u})

which will show you the merge base's commit subject and any tags or other references on that commit.

Just thought I would share what has ended up working for us, after some trial and error, based on the input here.

On the individual client server, when we want to target a specific revision for the build script we make a new "local" branch on that server.

If the revision/commit we are interested in is 7d65769ae9ba4ac9f92349feca8be3c70aacfcd6 then we run the following command

git checkout -b 7d65769ae9ba4ac9f92349feca8be3c70aacfcd6 7d65769ae9ba4ac9f92349feca8be3c70aacfcd6

This gives us a local branch where the latest revision number is 7d65769ae9ba4ac9f92349feca8be3c70aacfcd6

Now running

git rev-parse --abbrev-ref HEAD

returns the expected revision/commit (7d65769ae9ba4ac9f92349feca8be3c70aacfcd6 - obviously), so the build script runs. We do not add any remote tracking (since there is no remote equivalent branch, and we do not push this local branch to origin) thus we are not polluting the remote/origin with branches or tags which essentially is a pointer to a client specific test install.

So in conclusion - a combination of

git checkout -b <commitSHA> <commitSHA>
git rev-parse --abbrev-ref

Gives the same results as the old subversion commands

svn up -r <revisionNumber>
svn info -R | grep "Revision\:" | sort -k2nr | head -n1
(get revision info recursively, order by revision number desc, limit 1)

Thank you to all that took the time to answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM