views:

124

answers:

1

Hi there,

I have been studding GIT for the last couple of weeks in an attempt to get my team's code under control. Unfortunately the code we work with is a proprietary language with some peculiarities which is keeping me from finding a practical enough workflow to be implemented. Still, I'm probably not aware of all GIT's capabilities so I ask you guys for suggestion. I will divide this post in three: 1) how are my files; 2)the workflow we've figured so far; 3)options I reckon for the future.

My Files then;

As I said this is a proprietary script language, in which within the code itself you will find tags regarding configurations (servers, DB's and other stuff). It might sound strange, I know, but technically this code is a big complex configuration file. Well, it can not be changed, for now lets just leave it.

I also have two different environments: dev and prod, and I guess it's uses are evident. Due the odd way the code is thought, if you compare the script in dev to the same one in prod you would see:

prod:

CodeCode += Code(0)
Code{1} ...
CodeConfig = "ConnectionToProducionDB"
SomeMoreGenericCode.doSomething()
(...)

And in dev it would look like:

CodeCode += Code(0)
Code{1} ...
CodeConfig = "GoToSomeDevDB"
SomeMoreGenericCode.doSomething()
(...)

That would be it regarding the files.

Now, what have been figured;

At first glance, it seemed for me a classical lets branch it situation and so I've done.

[create a folder and init it]
[copy my code from production and add/commit it]
$ git checkout -b dev
[change these lines with 'CodeConfig' to the dev settings]
[go happy coding and commiting]

After a while, coding and tests are done and it is time to merge into production. That's when the problem starts.

A simple git merge dev (from my master branch) will merge the codes mostly ok, but the configs will be also transferred to the master branch, as from GIT's POV this is one of the updates in the code itself. While in this short code it wouldn't be a problem, in the real situation I might have re-configured ten or twenty sources and rolling back one at time isn't quite a pleasant (nor a reliable) task.

Of course, when using branches I do want to be able to merge my code in order to keep my commit history and comments. I just need it to be done in a more customized way...

I have tried a couple different things to work this out, but had no success. Seems that GIT's merge is just too smart for me :(

For instance, *.xml merge=Unset into my .gitattributes file. Or a custom merge driver into ~/.gitconfig trying to cause the auto-merge to fail (not sure if I got that right though).

Possible solutions I thought;

As I said, I am probably not aware of all GIT's functions, so my options are bound by those I know. I appreciate your innovation ;)

I though the simplest way would be if I could disable any auto merging and do it all manually (the codes aren't so large, and I'd have to look into it anyway). After that I'd create a simple merge driver that would pass all the code changes (not only the conflicts) to something like WinMerge or Kdiff3 where I'd get the job done. Unfortunately I didn't manage to get it this way yet.

My last attempt resulted in a lengthy and unpractical workflow, but I'll write it here so you can have an idea of my goal.

  1. init repo proj1
  2. copy prod files
  3. first add/commit
  4. $ git checkout -b dev
  5. configure dev settings
  6. code/commit dev cycle
  7. copy dev files to tmpDevDir
  8. $ git checkout master
  9. use WinMerge to compare tmpDevDir against proj1[master branch] and apply only desired changes
  10. commit proj1[master branch]
  11. $ git merge dev
  12. merge conflicts where needed
  13. $ git diff HEAD HEAD^ to review merge result and revert the merged configs
  14. $ git commit -am 'final commit for the production code'

And well... not nice.

Would anyone have ideas for a more practical workflow or other commands which would help this out?

thanks a lot,

f.

+4  A: 

It a classic "config file" situation (even if your files are not exactly config file).

The usual solution is to:

  • put only variable names in your code
  • extract the values specific to each environment in their own files
  • version a script able to generate the actual code (the one in which variable names have been replaced with their values depending on the current environment)
  • set a filter driver (see Git ProBook) to automate the variable substitution (meaning no "new files" are created: only the current code is modified on git checkout -- variable replaced by values --, and "cleaned" on git commit -- values replaced by variables, and values put back in a separate config file if they have been modified)

alt text

That way, you don't have necessarily to create separate branches just because you have separate values in some files.
No complex merges, copy between branches and so on.

Just:

yourCode1.code
yourCode2.code
...
yourCoden.code
devValues.txt
prodValues.txt
scriptPutValuesInCode.sh
scriptCleanCodeFromValues.sh

and a filter "smudged clean"

*.code  filter=setOrCleanValues

git config --global filter.setOrCleanValues.smudge /path/to/scriptPutValuesInCode.sh
git config --global filter.setOrCleanValues.clean /path/to/scriptCleanCodeFromValues.sh
VonC
@VonC: Thanks! Well, that is a bit more complex than what I had figured but should do it. I will give it a try and tell how it went. Though, just thought of something: is there anyway I could tell GIT how to merge binary files? Let's say.. I have an OpenOfficeMerger.exe capable of doing three way merges with OO's files... could I define it anywhere? Coruse I made that up, but though if I could use custom mergers.. well.. that would be a way out :) thanks,f.
flpgdt
@flpgdt you can have simple merge driver (http://stackoverflow.com/questions/2920594/tell-git-not-to-merge-binary-files-but-to-choose/2920807#2920807) or more complex merge driver (http://stackoverflow.com/questions/2089560/how-do-i-merge-a-binary-file/2089609#2089609)
VonC
@VonC: Almost there, the idea of using a driver seem to work better ti my need (although I agree the string expansion is a lot more elegant). I have added an update to the question, appreciate your thoughts :) thanks!
flpgdt
@flpgdt: it seems it would be better to rollback your edit and make the "merge driver" a separate question: now my answer is not related to your question! ;)
VonC
@VonC: hehe fair enough, will do. :)cheers, f.
flpgdt