Reputation: 13
I have a git repo that contains
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.
Upvotes: 1
Views: 5187
Reputation: 13
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.
Upvotes: 0
Reputation: 8215
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.
Upvotes: 1
Reputation: 60557
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.
Upvotes: 0
Reputation: 60557
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.
Upvotes: 1