8 ms·
Git is the C of Version Control Tools
- mechanical_fish 18y agoMany git users say that the problem with learning git is to unlearn all the stuff you know about CVS or SVN, because git is just not the same. Now I understand what they're talking about. Beacuse Eric Sink is a smart guy, but he doesn't understand git yet. He's still following the Subversion workflow. The secret is that "git commit" is not a sacred act. Don't be fooled by the words. When you do an "svn commit", the result is written in stone in some centralized repository where it can break everyone else's builds, now and forever. When you do a "git commit" the result sits on your machine. It goes nowhere. This is distributed version control -- a commit just changes your local repo, and if it doesn't work you just undo it. (Or, alternatively, make seven more commits in your efforts to fix it, then use the mighty "git rebase --interactive" to smash all of them together into a single, perfect commit. Then you pretend that it was correct all along. Nobody else will be the wiser. You'll look like a genius!) So, if you want to pull half the hunks out of a previous commit, make a branch (you can make branches more easily than blinking -- this is git), pull out half the hunks, commit the result. Then compile and test. (If you like, you can probably use a post-commit hook to compile and test automatically.) If the tests pass, merge your experimental branch back into your development branch, then do the "git push" to the central repository. It is that push -- not any of your commits -- that is the point where you have to be sure that you're not breaking anything. And you can't use git's index to push files that have never been visible to your compiler and your tests. UPDATE: I have yet to actually use them, but another one of Sink's commenters reminds me that git has pre-commit hooks that seem to solve his specific problem. Here's something I googled up on that subject: http://www.nabble.com/git-pre-commit-hook--best-place-to-make-available--td20907299.html http://www.nabble.com/git-pre-commit-hook--best-place-to-mak... Again, I don't use such a thing, because I think it's kind of silly to insist that every local commit pass all tests. That's a recipe for failing to make enough local commits. I've been finding that it's better to make a commit every time you make any change that can be described in an English sentence. Then you have a little log of everything that you've done that you can rearrange with "git rebase -i" and turn into your final, pushable commits.
- jackowayed 18y ago>And you can't use git's index to push files that have never been visible to your compiler and your tests. That's true w/in your scenario but a little misleading because it's not always true. If you don't use the experimental branch, you can add and commit pieces of files, yet the tests will run not on what's committed but what's in your directory. So if you had print password_to_the_admin_interface for some reason, and then you comment that out/delete it and forget to add that part of the file, you test it and see that it's not printing the pass, but then you push and deploy and bad shit goes down. Just clarifying so no one's like "I can't push code I didn't test! Git is so safe!" and then allows disaster to occur.
- mechanical_fish 18y agoThat is true -- thanks for pointing that out. I generally don't do pushes without first handling all the local changes, one way or another (either committing them or deleting them) so this possibility had not occurred to me. But it is there. I'm guessing that you could fiddle with git's hooks to discourage or even prevent this problem, if you wanted to. For example, you could refuse to allow "git push" to be run from within a repository that contains uncommitted changes, and also include a requirement that your tests pass before the push commences.
- jackowayed 18y agoI do sometimes. Usually it's when I do one thing, then start another, then realize that I really should push the old thing first. So I add the old thing I did, commit, test (when I test. sometimes I'm bad and don't have real tests.) and push, leaving this half-finished method uncommitted. I guess I really should just git stash. C does not have nearly as many useful things built in as git.
- jcdreads 18y ago> Because Eric Sink is a smart guy, but he doesn't understand git yet. He's still following the Subversion workflow. His article makes it seem like he doesn't have his head all the way around git's internals, but I think his problem with git is a valid one: it makes it _much easier_ to do the wrong thing to the build than the relatively simplistic svn does, and it can be a drag to use tools that make breaking the build quite so easy. For big team projects it is, in that sense, very much like C programming, and even more like C++ programming: it's a lot of power, but it's way more than enough rope to hang yourself with, or for the guy in the next cube to accidentally hang you with: > ...you need to act differently than you do when you're in an environment that attempts to protect you from your own mistakes.
- jrockway 18y ago# So when you type "git commit", your repository will contain something that has never been compiled or tested. rolls eyes If you don't like a feature, don't use it. I can easily commit crap that doesn't work to CVS or SVN repositories too. But seriously, some people have the ability to reason about their code without having to run their unit test suite first. Not committing this patch: (defun foo-bar (baz) + "Here is some unrelated documentation that I don't want to commit with my other changes." (let ((quux 42)) is not going to break anything. But it will keep my doc change isolated, in the history, from other stuff I may be working on. If it does break something, you can always rewrite the history at a later date. (In Git, history is a tool to make development easier -- not an indelible audit trail for the suits.)
- briansmith 18y ago"I know this isn't going to break anything" is the rationale to every build-breaking commit in history.
- jcdreads 18y ago"It'll be faster to await the broken build email and roll back than to test this on my dev box," is another good one.
- jrockway 18y agoRemember, "git commit" doesn't share your changes with anyone else. Presumably you run the test suite before you "git push" to share your changes with others.
- Xichekolas 18y agoThis is why I prefer to create a branch for each 'feature' I'm working on, commit to that branch a bunch of times as I feel like it, then merge the branch back into the master branch once I know everything works. Running a full test suite before every commit just means you'll commit less often, which leads to bigger commits that are more likely to contain a smattering of unrelated changes.
- icefox 18y agoFor the Arora project when I do a commit it doesn't run all of the autotests, but it does detect that I am changing files X, Y, Z and lookup the matching autotests and run them. This results in very quick testing. I found having local hooks very powerful and you can do many things that you could never do on the server. http://benjamin-meyer.blogspot.com/2008/10/git-hooks.html http://benjamin-meyer.blogspot.com/2008/10/git-hooks.html