Git keyword-expansion or alternative

2019-06-09 01:40发布

问题:

Having read some postings here about this topic, I realize that there are quite some cons that speak against using keyword-substitution. Nevertheless, I need a way to solve following problem and hope that somebody might have an idea on how to solve this with git (whether or not with keyword-substitution):

I have a main application for which I use git as VCS. Parts of this main application (a certain set of XML-Files) are being used by a utility for which I also use git (separate repo).

Now, the main app and the utility have different release cycles, and whenever I release a new version of the utility, I copy over the most current set of XML-Files from the main application. Within the utility, this set of XML-Files is non-versioned content in git, so it's not even checked in to the repo.

As of now, whenever I look at different releases of this utility (which is managed by git and has tagged releases) I have no way of knowing which "version" (better: commit hash) the set of contained XML-Files is referring to.

So I was thinking: if I can have the latest commit SHA within those XML-Files (as a comment), I'd always know to which set of XML-Files a certain version of my utility refers to. Is there anything wrong in this approach or is this the way to go? If yes, how do I get the latest commit-SHA into my XML-Files? (I read that $Id:$ won't take the commit-SHA, but some "blob"-SHA?)

回答1:

Two choices

Using Submodules

You can build main app as repo + submodule for XML-data. Because you can't use part of git-repo as submodule in another repo, only full repo (Git-boys, FIXME), you have re-create utility-repo as "supermodule" and split repo into two - utility + XML-data

Main repo becomes also "supermodule" and will 1) include main app and 2) XML-data for app

Because Git maintain strict relation between changesets in main repo and submodule for all and any base changeset-id (Git-boys, FIXME), you can only know hash of main app and get related to this changeset snapshot of XML-data

Smudge-clean filters

While maintaining repos as totally independent, you can add tracking data into XML-files. Proper way to add any arbitrary keyword to Git-controlled data is Smudge-clean filters (see "Keyword Expansion" section and example for $Date$ keyword expansion)



回答2:

If that XML file is not tracked by Git, then there is nothing wrong with this. I think it is a pretty good idea to have the hash a build is based on somewhere visible, so you always now when something comes up, what version of the source code this is based on.

Just for the completeness, it is not possible to have the hash value within a file that is tracked. This is because the hash is made based on all the information Git has. If it would insert the value into some tracked file, then that file would be changed, and either you would need to do another commit, or the previous commit would have to be changed – which would cause a different hash value.

As your file is not tracked, changes to it will not change the hash value, so the above is not an issue. There are multiple ways of getting the current SHA1 hash, the simplest is probably simply by looking into .git/refs/heads/master. That file is the pointer for the master branch, and contains the hash of the HEAD commit in that branch. Of course you can change /master to any other branch if you like.



回答3:

Possible solution is to extend main application's build process so one of results would be packaged XML files. This packaged version would contain added information about main application's version. Such package would be convenient to bundle with external utilities etc.

During build you can obtain version information directly from git with either git describe or git rev-parse HEAD (see Injecting current git commit id into Java webapp)



回答4:

Ok guys, based on your input, this is what i did:

  1. Insert placeholders in my XML-Files: <!-- @GIT_VERSION@ -->
  2. Have ant pick up git version information, note that this is Windows:
  3. Have ant insert this info into my XML-Files while copying them over.

Code:

<target name="getGitDetails">
    <exec executable="cmd" outputproperty="git.revision">
         <arg value="/c" />
         <arg value="git.cmd --git-dir=<path-to-repo> describe --long --dirty --always" />
    </exec>
     <exec executable="cmd" outputproperty="git.currentBranchRef">
         <arg value="/c" />
         <arg value="git.cmd --git-dir=<path-to-repo> describe --all" />
     </exec>
 </target>

 <target name="build" depends="getGitDetails">
     <copy todir="<dest-dir>">  
         <filterset>
             <filter token="GIT_VERSION" value="${git.currentBranchRef} ${git.revision}" />
         </filterset>
     </copy>
 </target>

Thanks for your help!

See also:

How to lookup the latest git commit hash from an ant build script

Deriving application build version from `git describe` - how to get a relatively straightforward string?