Git’s Integration Manager Workflow for Non-Wizards
I like Subversion and I would continue to use it for all my VCS needs if my favorite development environment Xcode wouldn’t have abandoned it. Now I was in need for a workflow similar to Subversion’s vendor branches mechanism. By reading the Git documentation and other resources, I was convinced that Git’s Integration Manager Workflow would come close enough to what I need and so I wanted to implement the IMW.
Git is a distributed VCS while Subversion is a centralized one. The main flaw of distributed version control systems is, that code and structural improvements are smeared around a number of repositories up to a point where nobody can follow it up anymore, and eventually good work becomes lost. For example, take any of the popular projects on GitHub, and count the there called forks, and find tons of them which got local changes (perhaps valuable ones - who knows) which never made it, and never will make it into the master repository. For me as a physical chemist this is nothing else than generation of entropy, i.e. hot air. A centralized VCS inherently urges everybody to have more self-discipline. We know the saying, When the cat leaves the house, the rats are dancing on the table. So, from the Cat’s point of view Subversion is great. Those, who don’t like discipline too much, perhaps might like Git more. That said, the pragmatic approach is to take that what is available, that’s Git, and ranting is irrelevant.
The project under version control
The actual project got a few years of history by a single developer (me) using Subversion (a few hundreds of commits and about 100 source files). I managed already to git svn clone ... the whole original Subversion history into a bare Git repository on a dedicated server (FreeBSD), and I called this one Commons.git . I am able to clone a working copy of it to my development machine, and pushing/pulling does work as expected, also the whole SVN commit history is accessible, so up to this point everything looks fine.
Now, I want to set up the requisites for the Integration Manager Workflow for more developers, and reading some tutorials, I am stuck already right at the beginning. Some start by setting up empty repositories from the scratch, what does not match my case. In another tutorial I read 1. Fork your existing repository ... , however the actual Git commands, on how to fork are missed out, and Git does not have a fork command, I can clone something or create branches, though. While Wizards find their way through all these doubts and over all these obstacles, by enchanting something like Abracadabra and/or Sim Sala Bim , non-Wizards are stuck to enchant the actual Git commands into the terminal, which all are not very different yet. Git is a you ask for it, you get it tool - complicated, cryptic, powerful, unforgiving, dangerous, and non-Wizards better stay on the narrow road.
So here we go:
-
Generate the bare derivate repositories, for example
Derivate-A.git and Derivate-B.git from the common repository Commons.git on the server:
cd /usr/local/git-repositories/TheProject
git clone --bare Commons.git Derivate-A.git
git clone --bare Commons.git Derivate-B.git
...
-
For each of the derivates rename its respective
master branch to working , and branch of a new master . This approach avoids later on the freaking detached HEAD issue. On the server:
cd /usr/local/git-repositories/TheProject/Derivate-A.git
git branch -m master working
git branch working master
cd /usr/local/git-repositories/TheProject/Derivate-B.git
git branch -m master working
git branch master
...
git branch --list -a
master
* working
chown -R git:git /usr/local/git-repositories/TheProject
chmod -R go-rwx /usr/local/git-repositories/TheProject
-
The Integration Manager clones all repositories to his/her machine and adds the master branches of the derivates as remotes to Commons:
git config --global pull.rebase false
git clone ssh://git@server:11/~/TheProject/Commons.git TheProject/Commons
git clone ssh://git@server:11/~/TheProject/Derivate-A.git TheProject/Derivate-A
git clone ssh://git@server:11/~/TheProject/Derivate-B.git TheProject/Derivate-B
...
cd TheProject/Commons
git remote add Derivate-A ssh://git@server:11/~/TheProject/Derivate-A.git
git remote add Derivate-B ssh://git@server:11/~/TheProject/Derivate-B.git
...
git fetch --all
git branch --list -a
* master
remotes/Derivate-A/master
remotes/Derivate-A/working
remotes/Derivate-B/master
remotes/Derivate-B/working
...
remotes/origin/HEAD -> origin/master
remotes/origin/master
-
Developer A, Developer B, etc. then would simply clone respective working copies to their local development machines and would start working, e.g. A:
git clone ssh://git@server:11/~/TheProject/Derivate-A.git TheProject/Derivate-A
-
Developer A does some changes and commits & pushes these into the
origin/working branch of Derivate-A.git on the server:
cd TheProject/Derivate-A
git commit -a -m "description of the changes"
git push
-
The IM pulls the changes into his/her
origin/working of Derivate-A , picks the very changes for passing it into origin/master of Derivate-A and finally pushes it to the server:
cd TheProject/Derivate-A
git pull
git checkout master
git pull
git cherry-pick working
git push
git checkout working
-
The IM switches to his/her working copy of Commons, pulls the changes from
Derivate-A/master and pushes these into the origin/master branch of Commons.git on the server as well:
cd TheProject/Commons
git pull Derivate-A master:master
git push
Now he/she pushes the changes into each of the masters of the other derivates on the server as well (e.g. Derivate-B):
git push Derivate-B master:master
...
-
Finally, the IM switches to each of his working copies of the other derivates, then pulls the changes from the
origin/master branch and pushes these into the origin/working branch of the respective derivate repository, for example Derivate-B.git , on the server:
cd TheProject/Derivate-B.git
git pull origin master:working
git push
cd TheProject/Derivate-nn.git
git pull origin master:working
git push
...
-
The developers are urged to pull the changes into their local working copy before they would be able to commit & push anything to the server.
If something goes wrong in any stage, make a clone(1) of the local working copies and the respective repository directories - see also: https://github.com/cyclaero/clone. Then hard reset all affected working copies and branches to a common known good stage, for example:
git reset --hard master~3
git reset --hard working~1
...
Ranting is irrelevant, but I can’t help, I did not love Git before, and neither do I love it now nor will I love it anytime in the future. All this pushing and pulling feels like using the Plunger for clearing blockages in the flush toilet. Occasionally, you have to use it, but you don’t love it, and once the job has been done, you stow this ugly tool out of sight.
Copyright © Dr. Rolf Jansen - 2020-08-29 18:26:27
Discussion on Twitter: 1300091709855084546
|