When a group forms, one of the things it does, over time, is develop values. Different development teams have different values, and people that come into the development process have to learn and adopt those values. One value of the FreeIPA project that is very different from other recent projects of mine is this: The main code repository is only for “published” code. Work in progress should happen elsewhere. The main git repository should be easily readable.
As contrast, the repositories for RHQ, Candlepin, and Pulp are where developers use the main repository as the first line of check-in for a feature, and then reviews happen from there.
This model, the “clean repo” model, works if you have a distributed version control setup like Git. The individual contributor has to feel confident that his changes aren’t going to get lost, and can publish them to a personal but publicly accessible (and remote) repository.
It does mean that you want to be crafting your commit as you go. As changes get committed to master, you want to rebase those changes in front of your work. This might trip you up, especially if those commits modify the same files that you are modifying, but you just pay the price of integration sooner. It does mean that your end commit is going to go cleanly. If multiple developers are working on code together, you have to treat it as a deliberate integration, otherwise the mix of branches makes integration down the road gnarly. Thus, treat the end product of the sideline integration process as a patch to go on top of the public git repository, and be continuously crafting that patch. Keep the individual commits in one branch, but have another where you are squashing, reordering, and crafting the comments to the work in progress.
Local revision control, to include a remote but personal repository, serves a fundamentally different function than the repository that has the code being prepared for a release. While you may use the same tools to work with both, don’t confuse the one with the other. The personal revision control makes sure that what you do is reproducible and revertible. While the centralized repository provides the same support, it provides to different people, and in a different way. The centralized repositroy should not reflect every design decision you waffled on (should I call it happy? No, glad! no, Happy! no..I know, Content!) But should instead reflect in a commit a reasonable sized chunk of code, with copyright to a single entity, encapsulating a related piece of functionality and reviewable by a normal human being.
On Friday, I pushed code to the FreeIPA Git repository, from my personal git repository’s main development branch. The push was not in the right format, and really muddied the waters. Here’s how we have decided o deal with it.
A vital aspect of any open source project is the community. The Git repository is part of a contract with the community: Here is where you can find the canonical version of our current thinking on the next versions of the project. If we were to merely revert the commit such that all of the checked in code just disappeared, we would be breaking faith with our community members. Thus, the “bad” push needs to stay around, if only to serve as an object lesson. However, we want the git repository to tell the tale of the next version. It should be simple, straight, forward, with minimal branching, again, only for important reasons. To balance out these two ideals, we will rename the master branch to webui-details, and then create a branch from the last known good commit prior to the unwieldy checkin. This new branch will be named master. Here are the two commands, executed on the main git repository, that changes the branch while maintain the history:
git –git-dir=$REPODIR branch -m master webui-details
git –git-dir=$REPODIR branch master d4adbc8052faf18fb31e7b1865037aa107067d4b
With these two commands, we will have changed, not history, but the intention of the main repository tree. The end states of the code will actually be identical, since we have checked in a commit to the current master branch that undoes all of the nastiness. With this change, we maintain the value of having the repository tell the tale. It also makes the tools easier to work with, as techniques like a binary search and so forth would not work with the gnarled mess.
This is not transparent to the end user. A git user that fetched from origin, and then checked out the a branch tracking orign/master would see
Your branch is ahead of orign/master by 251 commits.
The cleanest way to reset this, as far as my git knowledge can say, is:
git fetch origin
git checkout master
git branch -m oldmaster
git branch –track master origin/master
This renames the local branch, and then recreates the tracking branch.
We apologize for the inconvenience.
Deadlines can often produce major stress on developers. Resist the urge to check code in just before a deadline. That code is often the worst code you will write. The closer to a deadline, the more important it is to follow proper code review processes. You will probably make more progress, faster. As an old Infantryman once said to me “Make haste slowly.”