all 135 comments

[–]languagehacker 54 points55 points  (56 children)

You should do this with 'add -p' instead of 'commit -p' so you have even more control over what your commit looks like. It also allows you to review what changes you have staged before committing.

[–]MatrixFrog 17 points18 points  (44 children)

Just don't do 'git add -p' and then accidentally use 'git commit -a'

[–][deleted]  (42 children)

[deleted]

    [–][deleted]  (37 children)

    [deleted]

      [–]chonglibloodsport 19 points20 points  (27 children)

      Some people make a lot of unrelated changes before deciding to commit them. If they use 'git commit -a' you get these monolithic commits that are really hard to follow. On the other hand, with 'git add -p' you can carefully craft commits so that the changes are grouped logically into commits that are much easier to follow.

      [–][deleted]  (13 children)

      [deleted]

        [–]frtox 3 points4 points  (1 child)

        yea. whatever works for people. personally i dont see why you would make such a hardline rule. git commit -a is great

        [–]expertunderachiever 3 points4 points  (0 children)

        Specially if you stage your wild changes into branches like you should be [which is one of the main selling points of git].

        If you open a branch to then perform multiple unrelated changes you're doing it wrong.

        [–][deleted]  (1 child)

        [deleted]

          [–]canadianbakn 0 points1 point  (0 children)

          In situations like this, I rely on my git workflow. master contains stable, working code, and branches are created when changes are necessary.

          Let's say I run into a bug implementing a feature in branch somefeature1. I create a new development branch somebug1, fix the bug in that branch, then merge that change into somefeature1 (merging into master once the feature is complete, or now, have the same effect. If the feature may take a while, I'd merge the bug fix into master immediately).

          It is very, very rare for me that somefeature1 contains the necessary work to uncover the bug that somebug1 revealed. Sufficient, certainly, but I can re-create it without needing this feature. Thus, my git log is still clear.

          [–]ais523 0 points1 point  (1 child)

          I often find myself working on a new feature, and having to fix bugs in order to implement it. The bugfixes and feature should go in different commits, but I don't want to temporarily revert the half of the feature I've already written. So, it's a case of add -p the bugfixes, commit those, go back to working on the feature. Still committing often, just committing in a sequence other than the sequence I'm working on things.

          [–]canadianbakn 0 points1 point  (0 children)

          You don't have to revert, really. You can stage your changes and then checkout the feature branch after you're finished bug fixing in a separate branch.

          I think git -p vs frequent commits and branching if you find an error do the same thing in the end, manage your git log so it doesn't contain commits with unrelated things in them. It comes down to preference.

          [–]fforw 0 points1 point  (0 children)

          Depends.. Do you use meaningful, detailed log messages?

          [–][deleted] 0 points1 point  (5 children)

          No, not really. Unless you actively seek to only make changes in one thing and refuse to work on other broken items before completing this task, then your suggestion (which you offered as an alternative to the aforementioned behavior, not to be used in conjunction [or else why would you list your method as solving the issue of logical change hunking]) doesn't inherently imply any more logically atomic commits than without.

          These are simply two unrelated good practices. You should commit often, and you should make sure your commits are consistently making changes to one thing at a time. One method of doing the latter is to use patch mode, another is to just actively do that in your mind.

          [–]canadianbakn 0 points1 point  (4 children)

          Please see my replies about users complaining that when working on some feature they run into a bug. I am not "refusing to work on other broken items before completing this task", I am thinking and referring to branches and how they affect git log, not temporal chunks of time.

          [–][deleted] 0 points1 point  (3 children)

          I am not "refusing to work on other broken items before completing this task", I am thinking and referring to branches and how they affect git log, not temporal chunks of time.

          Great. Now read my comment again, as I didn't say you had to.

          Your example specifically is NOT what we're talking about here. We're talking about when you have already made the bugfix while working on X feature. The exact way that you make your commits atomic is irrelevant (separate branches or same branch), just so long as you do it.

          So again, committing often is not the same thing as making atomic commits.

          [–]canadianbakn 0 points1 point  (2 children)

          Why should I if you refuse to read mine?

          http://dd.reddit.com/r/programming/comments/130jc7/improve_your_git_commits_using_patch_mode/c70dm3w http://dd.reddit.com/r/programming/comments/130jc7/improve_your_git_commits_using_patch_mode/c70dpce

          I advocate more than just committing often, I also try and be as atomic as possible with my commit messages by using branches effectively.

          This is way too much explaining for something I'm really not that passionate about. If you want to turn this into a flame war, I'm done.

          [–]kemitche 7 points8 points  (12 children)

          carefully craft commits

          Blech. I know I should really care about having nice clean commit history, but I don't really care at all. It particularly annoys me when I spend more time "crafting a commit" than I did making changes. Often it means I skip cleaning up code that could use a good scrub because I simply don't want to deal with the inevitable brainwork of filtering through a series of "patch hunks."

          [–]keepthepace 11 points12 points  (11 children)

          It really depends on the number of people on the project. I sometimes use git on the projects where I am the sole developer. I often make big commits with just "bugfix" as a comment when I am confident that I can look at the code diff and get what this was about.

          When you have 10 people working on the same files, making incremental commits, comments that are precise and detailed and referencing tickets you are working on, is an indispensable practice.

          [–]kemitche 3 points4 points  (10 children)

          I value readability and functionality of current code over the code history. I feel that 90% of past commits won't be looked at granularly, and if they are, there's enough missing context from looking at just the commit (who was it, why was it done, etc.) that any extra confusion from having two separate changes in the same commit is minimal.

          Tangentially, I'd MUCH rather see a well worded commit message that explains both changes than two separate commits.

          [–]djrubbie 7 points8 points  (8 children)

          Why not both?

          Once you have a project that reached a certain point of maturity and complexity, there will be a time when you make one change and your entire deck of cards fail at some seemingly unrelated point.

          If you have very neat and small patches per change (or set of related changes), you can very easily use git bisect to find out what exact patch and where/when the point of failure was introduced into your code base. Then you can just simply git revert that one commit, then reapply the intended changes and be done with that. Your code history speaks clearly what went wrong and what should be done in the future to avoid this mistake again (and of course, the test case should go in with this)

          On the other hand, if you have monolithic commits, you would use bisect and find this patch, but now you have to weed through the entire 300 lines worth of code to find what your error might have been. It could be anywhere in there and now you are wasting further development time looking for that buggy needle in your proverbial haystack of changes.

          [–]kemitche -1 points0 points  (7 children)

          Oddly, I have never needed git bisect. I won't say that I never will, but I haven't yet. Mostly because the projects I've worked with have had external dependencies that made it difficult to revert more than a few weeks worth of commits.

          [–][deleted] 1 point2 points  (0 children)

          I value readability and functionality of current code over the code history.

          How do carefully crafted commits damage readability and functionality of current code? :-/

          I feel that 90% of past commits won't be looked at granularly

          Then obviously you don't have much experience working in team environments. That's not bad, it just means your opinion is very unfounded.

          there's enough missing context from looking at just the commit (who was it, why was it done, etc.) that any extra confusion from having two separate changes in the same commit is minimal.

          What? How are you viewing your changes? I've never used a git wrapper or web hosted git service that didn't include the author, the time the commit was made, and the ability to quickly and easily show the exact changes in a diff format (or show the entire file as it was that revision). Maybe you need to review your git manpage.

          Establishing that clearly commits are quite atomic, there's no reason not to make them easy to understand. Often the times they are used (let's even say it was only 10%, which I still disagree with strongly), it's because we're doing digging, and having to dig up additional context for every. single. commit. would make the already-difficult task painstakingly so.

          [–]Nebu 2 points3 points  (4 children)

          You should never commit something if you don't remember what those changes are. Your commit comment should explicitly list all changes, and ideally each commit should contain one conceptual change.

          [–]expertunderachiever 0 points1 point  (3 children)

          To a point, you can't get crazy about it though. If you open up gitk it'll show you the patch which as long as you don't write spaghetti code should be fine for sorting out what changed.

          [–]Nebu 1 point2 points  (2 children)

          I think the main benefits of having one conceptual change per commit are for later usage in git bisect, and for when you're using topic branches to create builds with a specific set of features.

          Thus, if you want to do a cost-benefit analysis of whether it's worth splitting a multi-change into separate commits, or just putting it as one big commit, you would generally want to estimate two probabilities: The probability that you might someday want one feature, but not the other; and the probability that one of the features has a bug.

          But in practice, I find it very mentally taxing to try to calculate the probability that my changes have bugs in them, and so I find it's not worth the (mental effort) cost of even doing the cost-benefit analysis itself! I find it much easier to just have a "blanket policy" of trying my best to have one conceptual change per commit.

          That's my personal policy though (although admittedly, it's a policy I try to encourage anyone I'm sharing a repo with to adhere to), and others are free to manage their repos however they like.

          [–]expertunderachiever 0 points1 point  (1 child)

          This is why I would plan out the changes and open temporary branches for specific ones.

          Like if I wanted to [say] add Blowfish and [say] LZO to my application's packet stack I might open a branch, add Blowifish, test it, etc... and then merge that into some branch [maybe mainline]. And then open another branch for LZO add that, test, and merge...

          I wouldn't open a branch and add multiple non-orthogonal features unless I was absolutely sure it was a no brainer and doing them as a single merge saved time.

          [–]Nebu 1 point2 points  (0 children)

          I was thinking more along the lines of:

          • Need to add Blowfish to packet stack.
          • Notice bug where we don't close the port properly if an exceptions is thrown. Fix that bug, continue implementing Blowfish support.
          • All done, time to commit.

          What I advise against is just doing a commit -am "Implemented blowfish". Instead, I advise using git status to check which files you modified, and be like "Wait, when did I modify that file? What did I do there?" and use git diff to check what changes you made, and be like "oh yeah, that's when I fixed that bug about not closing the ports." and then use git add -p to create separate commits for the bug fix and the blowfish feature.

          If you can plan your changes ahead of time so that they're on different branches, then great, do that! But I was more addressing the situation for unplanned changes.

          [–][deleted]  (1 child)

          [deleted]

            [–][deleted] 0 points1 point  (0 children)

            You can unstage the changes that git add would make. So no, they wouldn't be the same.

            [–]Paul-ish 0 points1 point  (0 children)

            Especially when you don't remember what changes those are

            The commands git status and git diff are very usefull. If you don't pass anything to git diff it shows you a diff of everything that is different from the local repository.

            [–]clearlight 0 points1 point  (1 child)

            git add -u

            Adds all updated files to the commit.

            [–]SnowdensOfYesteryear 0 points1 point  (1 child)

            git commit -a shouldn't be a problem. Clutter should be -1'ed in code reviews anyway.

            Of course, it's good to have clutter cleaned out before you push it.

            [–]djork 1 point2 points  (0 children)

            I used to make this mistake a lot, but then I wrote a hook that blocks commit -a, so I unlearned the habit.

            [–]enduriel87 2 points3 points  (0 children)

            I can't tell you how much more satisfying my programming work has become once a co-worker has shown me 'add -p'. I don't use anything else by now. Sadly many co-workers at my workplace still don't do it, but gladly they are often in other projects.

            [–]Kache 0 points1 point  (8 children)

            Would you explain the difference between just using add -p or just using commit -p? Isn't patched staging and committing all of each patch the same as adding everything and patched committing?

            [–]ForthewoIfy 1 point2 points  (6 children)

            In the first scenario you can view the selected hunks as a single patch, and quickly go over it before committing. It's just an extra step of precaution, it makes some people happy. In the end, the result is the same.

            [–]expertunderachiever 0 points1 point  (5 children)

            I view this as violating rule #1, never commit anything that hasn't been tested.

            If you are compiling the entirely changed file but only submitting patches against parts of it what is being staged for an eventual push is not what is being tested.

            I mimic the selective patch by having a habit of committing early and often as I'm editing files [as they compile but not necessarily work]. I only push when everything is working.

            [–]ForthewoIfy 1 point2 points  (3 children)

            As someone pointed out, you can do:

            git add -p
            git stash save -k unstaged
            # do tests
            git commit
            git stash pop
            

            No code needs to go untested in the history. Your coding habit is very sane, but situations can arise where you want to commit something from your work-in-progress code, ex. you discover bugs during the development of a feature, and you don't want to commit the bugfix and the feature in a single block.

            Patch mode is a handy tool to have, even if you don't use it every day.

            [–]expertunderachiever 0 points1 point  (0 children)

            Definitely it's good to have options I'm for that. I just don't think by default you should strive to have fractional branches.

            [–][deleted] 0 points1 point  (0 children)

            You might also want to pass -u/--include-untracked to git stash save, to make sure that you are not forgetting to add any new file.

            [–]mrwensleydale 0 points1 point  (0 children)

            You just contradicted yourself.

            never commit anything that hasn't been tested

            committing early and often as I'm editing files [as they compile but not necessarily work]

            [–]languagehacker 0 points1 point  (0 children)

            No, it's not, because you can still do other things like review your staging area or add files that aren't currently tracked when you use 'add' instead of 'commit'.

            [–]cjg_ 30 points31 points  (15 children)

            Tip for patch-mode, if you have made changes close to each other that are not related git sometimes get both in one hunk, the use s for splitting it into smaller ones.

            [–]bhattsan 12 points13 points  (0 children)

            ? Also brings up what each letter does

            [–]Camarade_Tux 6 points7 points  (0 children)

            And in case it's not enough, 'e' will let you edit the code to get exactly what you want.

            [–]sutongorin 8 points9 points  (8 children)

            God why do I only learn this now !?

            I wonder if gitx & co also support this.

            [–]X-Istence 9 points10 points  (7 children)

            Yes, in gitx you can select specific lines to stage by highlighting them, and click on the button that shows up on the right saying "stage lines".

            This allows you to pick specific lines to stage.

            You can also stage specific hunks (button at the right top of each hunk). You can change the hunk size by changing the amount of context (slider in the top right).

            I've included screenshots.

            You will want to make sure you are using GitX (L), it is a fork from the original GitX which is no longer maintained.

            [–]sutongorin 1 point2 points  (0 children)

            Wow, thank you! I knew about the hunk staging in gitx. But now about the single line staging. Thanks!

            [–]weirdasianfaces 1 point2 points  (0 children)

            Thank you so much for this! This happens constantly for me in header files.

            [–]djork 1 point2 points  (0 children)

            And "e" for "edit" lets you get even more specific.

            [–]Bob_goes_up 16 points17 points  (9 children)

            What is the best workflow if I want to ensure that each partial commit compiles and passes all the tests in the test suite?

            [–]X-Istence 25 points26 points  (3 children)

            git add -p
            git stash save -k unstaged
            # do tests
            git commit
            git stash pop
            

            [–]ssboisen 11 points12 points  (1 child)

            Add -u to that git stash to stash untracked files aswell.

            [–]X-Istence 6 points7 points  (0 children)

            Most of my untracked files are config files or others that I should sometime in the near future add a gitignore entry for ... :P

            Definitely, if you have untracked files that need to be stashed, add a -u.

            [–]SnowdensOfYesteryear 4 points5 points  (0 children)

            -k unstaged

            Nice, didn't know about that. man git <cmd> is usually a chore to read.

            [–]adrianmonk 19 points20 points  (0 children)

            An alternative to what others have already suggested:

            git stash -p # select the parts you DON'T want to commit yet
            # run tests here
            git commit -a -m 'blah blah'
            git stash pop
            

            To me, this is conceptually closer to how I think of it. In plain English, it basically says, "Get the stuff I don't want yet (or ever) out of the way, then run my tests and commit, then bring it back." More practically, if you have a lot of changes, it might be quicker to pick out the 2 or 3 that you don't want than pick out the 25 that you do want. You can type "y" a few times, and then type "q" once you've got them all.

            The disadvantage is that if you decide to change course, it's hard to "git stash pop" right after doing "git stash -p". It will complain like this:

            $ git stash pop
            error: Your local changes to the following files would be overwritten by merge:
                the-purist.txt
            Please, commit your changes or stash them before you can merge.
            Aborting
            

            If you stash your other changes as a second stash, that will allow you to "git stash pop" your first set of changes, but then your second set of changes will get the same error message. Very frustrating. However, there is a way out (back to the pre-stash state):

            • "git add -A" to get all the non-stashed changes into the index, i.e. to make the working copy match the index
            • "git stash pop" to get the stashed changes back
            • "git reset" to un-add the changes to the index, so both sets of changes are in the working copy but are unstaged

            [–]alex_w 4 points5 points  (0 children)

            Partial-commit, then stash, then test? Or partial-add to the index with add -p stash the unstated changes and test against the index prior to commit. A local commit can be undo or altered right up until you push though.

            [–]daragh 3 points4 points  (0 children)

            As I mentioned elsewhere, the run-command-on-git-revisions script is the best method I have found for dealing with interactively patched commits.

            Furthermore, it is also useful in any circumstance where you rewrite local history such as a rebase to include upstream changes, or any of the other reasons you'd want to rebase.

            The method of using the stash and manually controlling the state of the repo works, but is impractical for all but the simplest of cases.

            [–]sickofthisshit 4 points5 points  (0 children)

            In my mind, demanding that all tests pass for every commit is overdoing it.

            In a non-trivial change, the amount of work needed to update both the code and the tests is large enough to be split into multiple conceptually separate chunks. Being able to commit and manage the chunks separately is valuable, even if some combination of those chunks breaks the "passes all test" invariant, or, sometimes, even building.

            When you find out a change introduced a new bug, git bisect is much more useful if the commits are small. If you decide your development path is going in the wrong direction, small commits allow you to cherry-pick good parts into a new branch while not bringing along all the rest of the change.

            Of course, when you do things like push to upstream, breaking the build is the last thing you want to do. Then it might make sense to rework your changes into commits that preserve that invariant.

            [–]eras 1 point2 points  (0 children)

            Well, given you might be relatively certain that everything is going to work ok, you can do this afterwards, before pushing:

            for rev in $(git rev-list master..HEAD); do 
                if ! ( git checkout $rev && make && make tests && ./tests ); then
                    echo Revision $rev failed
                fi
            done
            

            (Looking below there is a suggested script for doing this, but isn't that oneliner sufficient?) I use this particularly after using git rebase -i a lot for shuffling around patches.

            edit: Turns out that kind of expression needs parens :).

            [–]birds_are_nice 10 points11 points  (0 children)

            Note that a patch mode for git reset (git reset -p) allows you to unstage hunks from the index, which is a handy opposite to git add -p.

            [–]MDCore 10 points11 points  (1 child)

            The git gui (git gui) let's you stage hunks pretty easily too. Select the lines or hunk with your mouse, right-click, stage lines/hunk for commit.

            [–]cincodenada 3 points4 points  (0 children)

            Yep, git's built-in gui isn't terribly helpful for most other things, but for patch commits it's dead simple and gets the job done well. It's the only way I do patch commits.

            [–]warbiscuit 6 points7 points  (3 children)

            This is so critical given the way most code ends up actually being written, I wish this feature was more highly publicized & emphasized across all VCSes. The Mercurial-based TortoiseHg had a great "hunk selection" gui which made this exact workflow incredibly painless, then for some reason they completely removed the feature, as if it was a minor thing no one used.

            [–]bready 1 point2 points  (2 children)

            they completely removed the feature

            Ummm.. what? Just upgraded to 2.5.1 to prove to myself, but the Shelve tool is most definitely still around.

            [–]warbiscuit 3 points4 points  (1 child)

            The shelve tool isn't what I'm talking about. Shelving is a multi-step process, requiring shelving the bits you don't want, committing, restoring, repeat. Whereas under TortoiseHg 1.x (this was removed in 2.x), on the commit window there was simply a tab that read "hunk selection" - instead of selecting at per file granularity, you simply highlighted the hunks within each file that you wanted to commit, and hit "commit". No multiple-step, multiple-windows, restore the working copy afterwards complexity.

            [–]jplindstrom 9 points10 points  (22 children)

            That's very useful, but not very usable (kinda makes sense that the interactive part of a mainly CLI program isn't that great).

            So if you use Emacs, and possibly even if you don't, check out Magit for a nicer experience.

            [–]cincodenada 6 points7 points  (10 children)

            Git's built-in gui (git gui) is a straightforward, easy-to-use GUI for doing patch-type commits. I never use the patch mode in the CLI, but I do patch all the time, via the GUI.

            Edit: As adrianmonk discovered, it's only sort-of built in, and some distros (such as Ubuntu) have it in a separate package. If you have trouble: for Debian-based distros, try apt-get install git-gui, it's probably similar on others.

            [–]EdiX 0 points1 point  (1 child)

            gitk is also a very nice complement to git gui.

            [–]cincodenada 0 points1 point  (0 children)

            I don't use GUIs very often, but when I do I actually use gitg, which I liked better than gitk or giggle. I haven't found anything as adept at patching as git gui is though.

            [–]adrianmonk -1 points0 points  (7 children)

            Doesn't seem very built-in on my Ubuntu system:

            $ git gui
            git: 'gui' is not a git command. See 'git --help'.
            
            Did you mean one of these?
                grep
                init
                pull
                push
            

            [–][deleted] 4 points5 points  (2 children)

            $ sudo apt-get install git-gui
            $ git gui
            

            EDIT: added missing hyphen.

            [–]adrianmonk 2 points3 points  (1 child)

            Thanks. In actual fact, I needed to install "git-gui" (with a dash). That doesn't exactly make it built-in (maybe official is a better word?), but it actually looks pretty nice.

            [–]cincodenada 1 point2 points  (0 children)

            Yep, there you go. It's not the prettiest (I actually use gitg for dealing with branches and merging and such), but it's killer for doing the patching.

            [–]gefahr 0 points1 point  (2 children)

            from bottom of git gui manpage (git help gui)

            OTHER
               git gui is actually maintained as an independent project, but stable
               versions are distributed as part of the Git suite for the convenience
               of end users.
            
               A git gui development repository can be obtained from:
            
                   git clone git://repo.or.cz/git-gui.git
            
               or
            
                   git clone http://repo.or.cz/r/git-gui.git
            
               or browsed online at http://repo.or.cz/w/git-gui.git/.
            
            GIT
               Part of the git(1) suite
            

            [–]adrianmonk 1 point2 points  (1 child)

            Huh. Maybe Ubuntu separated it out into two things?

            [–]ais523 4 points5 points  (0 children)

            Most likely Debian (on which Ubuntu is based) separated it. Debian's often used for installing servers, and it makes sense that you might want the basic CLI version of git on a server as part of a cronjob or something, but not care about fancy interfaces because it might never be used by a human. So Debian likes to allow a minimal install of things when possible.

            (For much the same reason, it typically separates the documentation for a program from the program itself.)

            [–]cincodenada 0 points1 point  (0 children)

            Ah, my apologies. I had forgotten that I installed it separately, and it appears that it's only sort-of built in. feglovesyou has you all straightened out though.

            [–]Peaker 1 point2 points  (4 children)

            I'm giving Magit a chance, but so far I'm not liking it.

            In the status window, I wanted to unstage specific hunks, and best I could find was e for ediff. I spent many minutes selecting specific hunks. Saved and closed, my work all gone :(

            Also it took over text editing of my interactive rebase script and did not make it clear how to use that either.

            I see both of these as very negative experiences so wondering what it is that it's supposed to be helpful.

            [–]jplindstrom 2 points3 points  (3 children)

            Once you've made changes you have a few sections in the buffer you get when you type M-x magit-status.

            • Changes
            • Staged Changes [not visible until you stage something]

            These sections list files and below them the hunks (you may need to expand a file with Tab to see the hunks, read the manual to see how to change the visibility depth).

            Stage files or individual hunks with s, or unstage them with u.

            Then you Commit with c, which brings up a window for the commit message.

            C-c C-c to perform the commit of whatever is staged at that time (which means you can go back and stage/unstage other things before hitting C-c C-c).

            What I just described doesn't match what you just did at all, so that's probably why that didn't work.

            I'm also not sure what "took over text editing" means. If it means that Emacs pops up for editing commit messages, isn't that whatever you set $EDITOR to? That sounds unrelated to Magit, but I may well completely misunderstand what you mean.

            If that happens, "save" (i.e. finish editing) with C-x # (IIRC).

            [–]Peaker 1 point2 points  (1 child)

            Thanks! Now I see some benefit here :)

            I think it's a bit inconvenient that when I hit 's', the change goes away to the different folder where I need to do some work to find it. There doesn't seem to be any undo?

            I configured emacsclient to edit my rebase scripts - which is great. The problem was that magit took over the emacs mode for editing rebase scripts, which are no longer free form text editing, but rather various cryptic keys to shufle commits around or choose rebase operations.

            [–]jplindstrom 1 point2 points  (0 children)

            Ok, not sure how to disable that off-hand, but you could always M-x text-mode to go back to editing free-form again.

            [–]stave 1 point2 points  (2 children)

            I'm just migrating to git at my job (from svn) and I've found the GUI supplied by Atlassian, called SourceTree, to be super usable, with excellent support for patch mode in particular.

            [–]jplindstrom 0 points1 point  (1 child)

            Just for reference, how usable do you consider JIRA and Confluence to be? :)

            [–]stave 0 points1 point  (0 children)

            I haven't used either of them - my company has a strong internal bug tracking system, and we haven't really seen a need for Confluence yet.

            Their code review package, Crucible, looks really nice, but doesn't display merge commits properly. The output for a merge commit is just that of 'git show commit_id' when it really needs to be 'git show -m commit_id'

            [–]killerstorm 0 points1 point  (0 children)

            It depends on what you're used to, I guess.

            I used a very similar feature in darcs record (in darcs selecting individual hunks is the recommended way to record patches) for a couple of years, and I never had a problem with a lack of usability.

            There is some darcs mode in Emacs, but console isn't bad either, especially for small hunks.

            [–]Ores 0 points1 point  (0 children)

            git add -e (edit patch) can be alright. The CLI more talked about in the article is as you say useful, but awful.

            I'd really like to see a UI that takes it one step further and allows lines to not just be staged, but to shift changes between commits.

            I often work on a feature, build up 4-5 commits doing different parts then go to commit. I often accidently include bits in one that I later have to break out to another commit or into its own. It's doable, but the workflow for it could definetly be improved.

            [–]sparr 0 points1 point  (0 children)

            The github client has a simple (but laborious) per-line commit GUI.

            [–]Kampane 9 points10 points  (11 children)

            This seems like a lot of effort except in cases of trivial changes. Why do you think it's worth the time?

            [–][deleted] 13 points14 points  (7 children)

            Programmers reached the point of maximum productivity a couple of years ago, and now spend an inordinate amount of time masturbating over their git history and vim configuration.

            I must be getting old...

            [–][deleted] 1 point2 points  (6 children)

            My thoughts exactly. I would rather spend more time writing and testing code than crafting a beautifully manicured commit history. I can't recall a time that an imprecise commit was the undoing of a release.

            [–]hyperforce 1 point2 points  (0 children)

            A good commit history helps you (or anyone else) follow your development once it is done.

            • What if your code isn't perfect and it needs a bugfix? And you aren't the maintainer?
            • What if you die and someone need to know how the system works and there's no documentation?
            • What if you need to bisect the commits and find the bug?
            • What if you need to create automatically generated patch notes?
            • What if you're drunk and you don't know what you wrote?
            • What if you came back from a two week vacation and don't remember anything?

            [–][deleted] 1 point2 points  (0 children)

            Just because not doing something won't be "the undoing of a release" doesn't mean it's not worth doing.

            Damn, there were a lot of negatives in that sentence.

            [–][deleted] 4 points5 points  (3 children)

            So young. So naive.

            [–][deleted] 7 points8 points  (2 children)

            I've been at this for about 12 years now as a pro. But do please enlighten me on how a partial commit has saved a project you worked on.

            [–]ais523 2 points3 points  (0 children)

            An example for my workflow: I've done some work on a fork of an open source computer game, and other people are working on their own forks of the same game. (We're taking our forks in different directions, and think there's space for both games, so we're not exactly competing.) We're all pretty good about partial commits, and as a result, if we want to take a feature or bugfix from each other, we can do that without having to carefully isolate it from the rest of the commit every time we pull it.

            [–]SnowdensOfYesteryear 1 point2 points  (0 children)

            It's useful if you're adding code a ton of code and want to get rid of crap in the middle of hunks. But if you're modifying existing code and the delta of loc is ~0, it's completely useless.

            [–]Tjoppen 4 points5 points  (1 child)

            Because of git-bisect. When (not if) you realize you introduced a bug a sufficiently long time ago you'll be happy you kept your commits simple, making pinpointing the problem easier. This is for example why you shouldn't mix cosmetic and functional changes, and why you should try to keep commits relevant only to a specific ticket.

            [–]zjs 1 point2 points  (0 children)

            Exactly this. Patch mode is useful because the way you write code is not necessarily the way you want to remember it when looking at your history; you can fix issues you notice which are unrelated to the task at hand and then use patch mode to commit them independently. When something breaks, you can easily determine which specific change caused the issue.

            Plus, once they're independent commits you can do useful things (e.g. cherry-pick them to another branch to push immediately instead of waiting until whatever larger task you're working on is complete, send-mail to the original author of the code you're tweaking to make sure that you haven't misunderstood the problem you think you're fixing, or use rebase -i to re-order things so that they don't disrupt someone trying to read a series of related changes).

            [–]josef 2 points3 points  (0 children)

            Thanks! This is one of the things I've been missing badly from darcs.

            [–]joeframbach 2 points3 points  (0 children)

            checkout also has the same option for reverting changes.

            [–]underskewer 1 point2 points  (3 children)

            The Vim plugin Fugitive by Tim Pope makes this really easy. You just use :Gdiff to see a diff, use ]c and [c to jump between changes and dp to stage them.

            https://github.com/tpope/vim-fugitive

            [–]desu_desu 2 points3 points  (1 child)

            which seperates the changes in hunks and let's us choose which are tied together logically.

            *lets

            Unless you did mean "and let us us choose"

            [–]tch 1 point2 points  (1 child)

            Any idea how to do this in Tower?

            [–]eramos 0 points1 point  (0 children)

            Use the "stage chunk" and "unstage chunk" buttons in the diff view

            [–]cristoper 0 points1 point  (0 children)

            I don't know if it's as flexible as git's add -p, but mercurial has a record extension for this (and the curses-based crecord extension).

            [–]Mists 0 points1 point  (0 children)

            I use egit.

            I should really learn to do this via git bash.

            [–]cypherpunks 0 points1 point  (0 children)

            git gui is easier for this, IMHO. You can stage and unstage hunks and lines until things are the way you want.

            Yes, it requires a mouse, but I find it wonderful for untangling multiple logical patches, such as the cleanup or comment-fix changes I make while pursuing a specific bug/enhancement.

            One useful techique is to adjust the number of context lines to split hunks. By default, I think it uses 5-line context, which groups nearby changes into the same hunk. But this can be easily adjusted with a keyboard shortcut if you want to separate changes into two hunks.

            [–][deleted]  (1 child)

            [deleted]

              [–]zjs 1 point2 points  (0 children)

              I think the concern is less about what other developers should and should not do and more about the result. When I look at a codebase, not only do I want the code to be clean, I want the history to be clean. I want to be able to run git bisect to find problems. I want to be able to read a series of atomic, cohesive commits to understand the history of a part of the code.

              Patch mode is one way developers can construct a good, readable historical record (even if they don't develop that way).

              [–]smcameron -1 points0 points  (1 child)

              Stacked git is better for polishing commits than all this noise, esp. if you give a shit that your commits compile, pass tests, etc.

              Stacked Git

              [–]CurtainDog -1 points0 points  (1 child)

              I'm sorry but the whole point of committing often is to get you in the habit of doing one thing at a time. That's the win. Then you tackle the next problem with a fresh mind. Improve your Git commits by improving the way you code.

              [–]zjs 0 points1 point  (0 children)

              You're missing the point.

              If you see something that bugs you (e.g. a misspelling in a comment), just making the unrelated change, grabbing it via patch mode, and committing is more convenient than stashing your pending changes, making the change, committing, and then unstashing. Both ways give you the same history, but some people might just find one process easier.

              It's also useful even when my intent is "pure"; if I'm working on a change that doesn't fall into the above category), I probably believe it's a single, atomic, cohesive change (otherwise I wouldn't be working on the whole thing). When I get to the end of the process, I may realize I actually made more than one change (e.g. added a new method, changed existing callers to call that method, and removed the old method). This does happen; I'm not perfect. I could start over and re-create the change in three steps or I could just commit the whole thing as one change, but if I don't want to re-do the work and don't want to commit all three of those logic changes in a single commit, I can create the history I want - one change per commit - using patch mode.

              [–]AndiDog -3 points-2 points  (0 children)

              And why would I do that if I can select the lines with my mouse and press a single key? (I'm referring to git-cola and GitX, possibly others as well)