>Using branches heavily in your development can make you a better programmer like few other habits can.
It was really hard to keep reading after this line. It's like saying painting your bedroom red will make you better at sex. It's like saying getting a gas-powered golf cart will make you better at golf. It's like saying changing your mouse to be inverted on the Y-axis will make you better at computer games. All of these things change the experience, but they don't make you inherently better at anything. Just like branching during development.
I find it plausible that a golf cart could make somebody better at golf. Without the cart, a non-trivial amount of exertion is spent on a tangentially related task (getting from hole to hole) instead of on the primary task (getting the ball from hole to hole). Something that allows golfers to better focus on golfing could conceivably improve their game.
I really get tired of this sort of response where the one replying ignores the primary point in order to take issue with a single portion of one of several examples that bolstered it.
I am not ignoring the primary point. My point about golf-carts and better golfers maps back onto branching and better programmers.
To spell it out explicitly: I believe that modern version control systems, specifically ones that provide sophisticated branching facilities, reduce mental load on programmers and speed up tedious tasks. This could very well make people who take advantage of them better programmers (where "better" can be described in terms of efficiency). The less time I spend managing branches and doing merges/rebases the old way, the more time and effort I am able to devote to my primary task (actually programming).
I could manage patch files and tarballs with quilt, but I would be wasting my time and my productivity would drop. That would make me a "worse" programmer. If bad tools can hold me back, then better tools can improve me.
I think by "better programmer", he meant you will function better as someone who writes code in the context of a team. And using branches properly can (a) help other people grok the code you write, (b) help you maintain clarity with an influx of change requests.
Of course advice to "just use branches" is not going to make up for core deficits in your programming knowledge. But in my experience a lot of the trouble we get into on software teams is due to workflow problems and misunderstandings rather than "bad programming".
Sure a good chef will be able to cook an amazing meal with just a spoon, a frying pan and a steak knife. But, he will do better with a full kitchen. And if you want him to do it in a way actually capable of handling a restaurant - the full kitchen is needed. He may not be a better cook with the tools, but he certainly will be a better chef. Because you know, just doing cooking things is not the only aspect of the job of chef.
I think local commits are pretty useful, and local branches sometimes are as well. But "using branches heavily" is a pet peeve of mine. Git encourages lots of branching that in most cases is unnecessary (e.g. making feature branches for everything, never committing directly into master). When working with a team, everybody should be working on as close to the same codebase as possible, to prevent difficult merges later on. In my view, merging has a very non-linear cost based on how far apart the branches are, both in terms of time and amount of code changed, because it's more likely that the merge will have more tangled dependencies, and the code will be less fresh in the mind of whoever's merging.
Merge commits can also hide lots of information, like exactly how any merge conflicts were resolved, since they're buried in what is basically a squashed commit of everything in the merged branch since it diverged.
And finally, they make the commit history much harder to understand. I had to bug everyone on my team to run "git config --global pull.rebase true" just to have a somewhat sane, linear history without tons of merges in day-to-day development.
> When working with a team, everybody should be working on as close to the same codebase as possible, to prevent difficult merges later on.
I agree with this, but disagree that avoiding branching is a good way to do it. In my experience, the solution is more, smaller, feature-specific branches that get merged back to master quickly (within a couple of days if possible). If you need to maintain a long-running feature branch, it should frequently be rebased on top of master so that at any given point the likelihood of major conflicts is reduced.
I disagree with your analogies. I think git branching is more like a secretary with a very well organized filing system. Does the filing system make her better secretary? Maybe not necessarily - she could work twice as hard and still meet the boss's requirements. But a secretary with a stellar filing system will be more effective than she would be without one. and that does make her 'better'.
If you have git style branching available, you can commit half-finished ideas and save ALL your backup versions. Almost all my directories are littered with files called sourcefile.v1 sourcefile.v2 sourcefile.old etc. etc. With git if your current version hits a dead-end, you can easily switch back to an earlier branch before you went off the deep end.
At least, that's how I code. I generally just jam code in down different paths, often refactoring whatever I'm doing when a new understanding of something comes along, but often this results in another incorrect branch and I need to back up to 'semi-working' code.
> It was really hard to keep reading after this line. It's like saying painting your bedroom red will make you better at sex.
I had the experience that having to switch back to SVN made my workflow significantly worse, lowering my productivity a tiny bit and thereby making me a slightly worse programmer overall.
The importance and convenience of cheap local branches is nothing that will be known to someone who hasn't used them. If you are used to them, using a system without them makes you feel you are doing the job that the tool should do.
You seem to regard programming as the act of writing code. I, however, view programming as the act of creating software. And using branches heavily definitely helps me to be better at creating software. Having small feature-specific branches makes it much easier for others to review my code, which increases the quality of the code that gets merged. Improvements in code quality seems like a pretty good definition of getting better as a programmer.
The other really powerful thing with git is the ability to keep a long running branch and continually rebase with something like develop/master. That way you can resolve conflicts outside of the main line and then reduce the chances of a hairy merge.
I've found this to be very useful with large refactorings. It eases the pressure of having to stabilize everything before a release. If the refactoring isn't ready for this release, don't merge it back in.
Absolutely agree! Rebase is a great alternative to standard merges: it keeps your line of development clean and avoids having tons of "merge knots" in your commit graph.
This misses the biggest thing that made me initially switch to git: local commits.
I can do with only a single branch if necessary, but how the f*ck are you supposed to develop anything locally and roll back changes in subversion if you are never allowed to commit because it might break someone else's stuff?
I think there are other svn-alikes that might solve this problem (svk?), but with pure subversion it is the biggest roadblock for me (and I bet, a lot of other new coders).
It's something you can do in svn already. Granted, it's not as streamlined as it is in git, and you would need to commit to the remote server, but that's not the end of the world.
In the old days, before git existed, we used to have a space in the repo for each developer. You could put whatever you wanted in there. So if you wanted to go off on a tangent you just copied the code via svn, switched to that copy, do your work, commit as you please. When you were happy you could cherrypick / merge into the main branches of the code.
Git makes this stuff easier, but it was all possible with svn. Hell, it was probably even possible with cvs if you jumped through the right hoops.
Firstly -- it's on the server, as you said, which slows things down. Also, is there an easy way to rollback, if you don't have certain privileges on the server?
True, but it's a trade off. I've run big svn repos before where we couldn't have used git because it would have taken up too much space on the client machines.
In terms of editing the history it's generally just considered something that you don't need to do.
My point was not so much that git isn't better. It was more that the desire for the new tech makes people forget what the old tech could do. It happened when svn took over from cvs. It'll happen when the next tech comes along to replace it. That's life.
You can always use your own feature branch on the server. The only difference is online/offline access to it. Otherwise - do whatever you want - there are a lot of projects doing private branches (just by namespacing them by prefix) where people experiment.
Yeah, this can be quite a game-changer. Initially, people always undervalue this and think it's only good when you want to work on a plane.
But being able to commit locally makes stuff faster, makes you able to test things out - and only share code when you actually want to.
Totally agree. And no, it didn't invent it, but its the first system that has that, and has enough traction in the world to warrant being learned.
As to the features mentioned in the article, I agree in principal, and someday I'll even learn git well enough to be feel like trying to use them isn't a huge, mental drain from the focus of my actual work :-)
Well, this is Tower's blog, but stating that Git was "the first system that was deliberately built around" branching is too arrogant.
Nevertheless, branches are really just a (albeit nice) side-effect of the fact that Git (and Mercurial, for that matter) explicitly tracks _changesets_, not just _revisions_.
For one, Mercurial has branching as well. Although technically it was released 12 days later than Git, the motivation for both of them was that Linus Torvalds decided (for legal reasons) not to use BitKeeper for Linux kernel development and was in need for a replacement version control system.
Besides Git, Mercurial and BitKeeper, there is also Monotone, which is also a DVCS.
Git was built to replace a proprietary branch-centric (or merge-centric) versioning system that the kernel devs had used previously, because none of the other available systems were suitable (including several DVCSs, which must be branch/merge centric due to the nature of distributedness).
Also try looking into the history of the DaggyFixes idea (that a bug fix should be committed against the earliest revision to contain the bug and then merge into the active branches, rather than committed against current head).
Let's define "revision" to be "what the entire codebase looked like at some particular point in time" and "changeset" to be "a list of changes between one specific revision and the next specific revision".
Now, if we look at Subversion, we see that given a particular revision there's no way to reliably determine its' "parent", because the fact that r6 is followed by r7 doesn't mean that changes in r7 were based off of r6.
If we look at any DVCS, each commit would have an explicit reference to its' parent(s), so there's always a non-ambiguous way to reconstruct the entire "chain" of relationships between commits.
> Let's define "revision" to be "what the entire codebase looked like at some particular point in time" and "changeset" to be "a list of changes between one specific revision and the next specific revision".
Git tracks revisions then. Commits have a tree object that describes the codebase at the time of the creation of the commit. You don't need to transverse any previous commits to recreate that tree. Commits also have other commits objects listed as their parent commits, but they are not needed to examine the current state.
Git doesn't use deltas in the way that Mercurial does.
The only system I know of that truly tracks changesets rather than revisions is Darcs.
But from a more practical standpoint, tracking changesets rather than just revisions means recording ancestry ("commits also have other commits objects listed as their parent commits") such that you can freely create merge revisions and the system will Do The Right Thing with minimal hand-holding.
The internal repository format isn't really relevant here, it's about the way of thinking that the system is designed to support.
Mercurial storing deltas is just an optimization (sometimes it stores full snapshots): all manifests [1] refer to full file content, not deltas.
Let's put it this way: the key feature of DVCSes is that they store explicit relationships between a particular commit and its parents. This makes it trivial to reconstruct actual changesets as per my definition, which in turn makes merge machinery much more reliable.
Okay, that I can agree with. I just think it is misleading to say they are based on change lists since changelists can be derived but are not actually stored. (And in the case of git at least, the changes you derive may not be changes that a human made, per se (in other words, those changes are the output of rebase.))
Yeah, you're right. This company decided to write a blog post 100% related to the business they're in that has a good chance of being read by their target audience because the post is relevant to that audience. This will probably drive traffic to their site, and maybe help them sell more of their software.
Where I work we use master as the release-production-ready code. We branch of version branches from there. So a 2.5 release will be based off of master.
We work off of develop, and branch out topical branches from there, once complete merge to develop, test, once approved merge develop towards master.
And so on and so forth. It's very clean and makes it easy to test out other developer's feature as everything is encapsulated in a branch.
What would be nice is some kind of simple Git that consolidates some of the multiple command sets that I have to use to do things that are just one command with SVN.
Also I miss the deterministic nature of SVN Revert, when I run that in SVN it really makes my working directory exactly as it was that morning before I started typing. With Git, well with EGit this isn't too hard, Team | Reset | Hard | References | ORIG_HEAD. It works for me.
I don't trust git stash and prefer to instead commit, leaving some message like "This is the first commit of branch foo", then rebase when I'm done. That way I don't have to worry about forgetting that I stashed changes earlier, or not being able to find the stash that I thought I did. The branch always has the latest code and i'll just rebase when it's ready.
This looks very interesting. I've been reviewing a number of the Git clients (SmartGit, SourceTree, etc.) It appears that this client integrates features and context that help one use Git. But I am not clear on how it improves on Git itself. What are the strengths of Tower beyond those features that are provided through SmartGit?
First, let me say that SmartGit is an excellent application, too. However, most people that chose Tower over SmartGit prefer our approach in regard to user interface, workflows, usability, etc. Tower goes a long way to make using Git both as easy and as comfortable as possible.
However, don't believe me ;-) I recommend you download the free trial from our website and see for yourself.
I'm still interested in something which tracks "moves" well. Moving a big block of text/code into a different file is still lacks the easy-to-see guarantee that the disappearing and appearing two blocks are the same. Do you know any techniques for this?
Moving a block of code within a file is just a delete+insert as well. I don't think git differentiates between moving something within a file and moving it between files the way other systems do, but as far as I know there aren't any systems that actually understand and track refactorings rather than tracking diffs.
I used to think that branching was awesome. And then I realized that what was REALLY awesome were small, atomic commits. They are the thins that make code increments readable and let you find the problems better.
Branches are good for isolating longer-running changes but the merges are often not small. The longer the branch the more chance the merge will introduce subtle bugs. And the merge has so many lines change, where do you begin to see where the bug is once you've combined branch A and B?
I've had a coworker argue that NOT having long lived branches avoids this. And he said at Microsoft they were just fine with mainline - and as soon as they started branching the trouble always started during the merge.
I guess it's a combination:
a) Granular commits are an essential basis of good version control. Big, bloated commits (maybe even combining code from multiple, different topics) will sooner or later bite you.
b) Integrating often. I think you can be successful with long-lived branches, but you need to have more discipline and not forget to re-integrate from time to time. Integrating late will naturally raise the risk of conflicts - because, simply, more changes accumulate.
My first attempt at "revision control" was multiple copies of files: "main.cpp", "main_2.cpp", "main_2final.cpp", "main_2finalb.cpp", "main_2finalb_forreal.cpp", and so on.
This scheme clearly doesn't work.
So, in highschool, we started using SVN. We used it less for its versioning abilities than we did for its ability to function like a distributed file share (this was before Dropbox, which sucks rocks anyways). We stored lots of binary files in it (images, models, etc.), and sadness resulted, but it beat the hell out of the alternative.
In college, my SVN-foo upgraded--we used SVN properly: updating, resolving conflicts, and committing changes. It worked well enough, though it still sucked for binary stuff--and merging conflicts was a pain in the neck.
After college, we started using SVN more cleverly. We started limiting our commits to functional changes, and documenting very carefully what changed and why. We tagged branches for release, and kept the repo clean. We moved binaries off into their own repo.
At my first gig, we used SVN with Eclipse, which was pretty awesome. It had great merge functionality, it had great team support, and I even learned how to branch from mainline development in order to do my own projects. I did not learn, however, how to merge said branches back in any way which did not involve madness and suffering. Oh, and people would sometimes break the build, and if you were lucky you read that email (if they sent it!) before you updated in the morning.
My first few encounters with git were again using it as a distributed file share, this time hosted on Github--from hackathons and the like. I did not receive a very good explanation of it other than "that's what we're using for this project"; I suspect that unless you are really careful it is hard to explain to somebody new to git how to use it if you have experience yourself.
I later learned to use git to have multiple repos to push to, one for code, one for staging, and one for production. It was the most magical thing in the world--`git push production master` and then Heroku is showing my new website.
I finally learned branching and merging when doing my startup earlier this year; I'd heard about doing topic/feature branches, and we developed a workflow somewhat like GitFlow. I learned how that worked, and barring the occasional screwup found it very, very useful.
I'm currently implementing a helper tool for CI and issue tracking with GitFlow-style workflows. I've had to learn more about how to use the tool, how to manage branches, and all other things.
~
git is a much more complicated tool to use, effectively, than SVN--at the same time, I think that getting there is worth it.
I further think that people starting out learning a VCS would be well-served to use SVN; combine it with TortoiseSVN on Windows and it's pretty simple. `svn update`, `svn commit`.
That done, when you have a workflow where it makes sense, switch to git. Git shines for letting you rapidly test things out, and keeping you from stepping on other people's toes.
I have used SVN for remote team work, and for certain things it's great--library development, things where you need people not to sit on commits easily, etc. I think that SVN is a great tool for newer developers, and I think that it has uses to this day.
That said, once everyone is up to speed on basic git, your team should make the transition, because it enables you to have more complex workflows and do more powerful work.
It was really hard to keep reading after this line. It's like saying painting your bedroom red will make you better at sex. It's like saying getting a gas-powered golf cart will make you better at golf. It's like saying changing your mouse to be inverted on the Y-axis will make you better at computer games. All of these things change the experience, but they don't make you inherently better at anything. Just like branching during development.