1. 67
    1. 22

      Largely, I agree with everything in here, but I feel like there’s some logical inconsistency between two of the points the author makes. First, they give this argument for short lines:

      Easy-to-read code is easier to follow and understand which leads to fewer bugs and faster debugging.

      But then they argue for 2-space indentation:

      To make this work, and yet allow a few indent levels, the code basically have to have small indent-levels, so I prefer to have it set to two spaces per level.

      I think 2-space indentation and long lines have similar effects on readability. In my experience, such a small indentation amount makes it really hard for my eye to follow which level I’m looking at, which is not all that different from the way long lines make me lose track of which line I’m on when I have to jump all the way to the left to find the beginning of the next line.

      All of this is not to say I think the author is wrong, per se, but more to point out that using 100 columns rather than 80 allows you to use 4-space indentation, for readability reasons, and still keep all the other benefits of hard-wrapping at a relatively short column width. I tend to think it’s more important to have a column limit, and that it’s consistent across a codebase, than exactly what the column width is.

    2. 16

      I’ll just use whatever style the auto formatter tool that is configured on the project has, and if I’m starting one myself I’ll use the default settings, which usually set the column limit to 80 chars, and I’ll set it to format on save in my editor. It’s the closest I can get to a structural editing experience for most languages out there so I’ll take it.

      1. 8

        My sincere hope is that eventually, the growth of auto-formatters will heavily reduce the appearance of these conversations on the right way to format code.

        1. 3

          Not as long as there’s multiple formatters and no language-dictated way of formatting (ex. gofmt)

          1. 6

            I didn’t say eliminate, I said reduce.

            And yes, I was specifically thinking of language-specific and widely-community-adopted auto-formatters like gofmt and rustfmt.

            1. 4

              Go one step further. Syntax shouldn’t even be saved. Save the AST. Use structural editing like Lamdu.

              1. 1

                It’s an interesting idea, but it’s certainly not anywhere near the readiness-for-adoption of auto-formatters. This would require substantial structural changes in education for the field (academia, bootcamps, self-education), in tooling, and so much more.

    3. 23

      I don’t know why so many people use spaces instead of tabs for indentation. Always use tabs for indentation and if you prefer 2 spaces per tab set it as such in your editor. There’s no place anywhere where a tab is “defined” as an 8-space indent. Please learn to set your software up correctly and stop forcing your choice on the rest of the world.

      As a side-note, use spaces for alignment (e.g. multiline function arguments). In the ideal case, your code-formatting then shouldn’t depend on the number of spaces per tab.

      1. 13

        When people use tabs instead of spaces, and I edit their code, then what typically happens is that their code looks wrong: columns don’t line up. I have to change my tab size to match theirs before I can read the code. This happens for several reasons. Sometimes tabs and spaces are used inconsistently for indentation. Or sometimes tabs are used for internal indentation (eg, inside of //… comments). Or sometimes indentation is used to line up code in a case like this:

        int myfunction(float arg1,
                       float arg2)
        

        (Where the word ‘float’ lines up in lines 1 and 2.)

        With discipline and rigid adherence to a coding style that avoids these problems, then tabs can work. In my experience, other developers typically don’t have the discipline to write code that looks right when the tab size changes.

        Always use spaces for indentation. Then you won’t inflict this problem on other people reading your code.

        1. 20

          On the other hand, you’ll “inflict” your indentation size preferences on people if you use spaces. This is why no one can agree on this: they both have upsides and downsides, and it’s a matter of which downsides are “less bad”.

          The general solution is to use tabs for indentation and spaces for alignment, as FRIGN mentioned, which gives the benefits of both and (almost) always works well regardless of tab size. Tools like gofmt handle this automatically. There’s also “elastic tabstop”.

          1. 9

            In a given codebase, there’s plenty of stylistic choices which are taken and cannot be visually changed with a client-side switch (see for example the number of clang-format settings). Maybe it’s easier to accept that indentation is also one such stylistic choice, there’s probably too much thought wasted on this matter.

            1. 1

              Maybe; I don’t really have very strong opinions on it as such – there are more important things in programming or life to worry about – but at the same time, even though I programmed Ruby full-time for 2 years, I never really got used to the Ruby convention of 2-space indentation. It’s just too narrow for me.

        2. 15

          Always use spaces for indentation. Then you won’t inflict this problem on other people reading your code.

          You should rather use spaces for alignment. Indentation is used to semantically separate portions of code. Alignment is used to make the code more readable. They serve two different purposes, and can totally coexist withing the same code:

          /*
           * Tabs emphasized as ">·······" for clarity
           */
          int myfunction(float arg1,
                         float arg2)
          {
          >·······if (arg1 != arg2)
          >·······>·······return 0;
          
          >·······fprintf(stderr, "arg1 = %f, arg2 = %f\n",
          >·······        arg1,
          >·······        arg2);     // note the use of space AFTER the tabulation
          
          >·······return 1;
          }
          
          1. 1

            Exactly! If someone feels the need to align some code, this must be done in spaces, not tabs.

            (or use elastic tabs, if it is supported by given project and tools)

        3. 7

          The solution is to use tabs for indentation but spaces for alignment. So for the second line of your code example, tabs would be used up to the indentation level of int, and spaces would be used from that point on to align float.

        4. 3

          You’re conflating indent and alignment. In your example, both lines have the same indent and so should start with the same number of tabs. The first line has no alignment spacing, 15 alignment spaces.

          The latest versions of clang-format support this and so you can use tabs for indentation spaces for alignment and get the best of both worlds.

      2. 4

        A big reason for me for spaces is that things like diff and blame will prefix the lines. With spaces for indentation, all lines simply get shifted over by a constant amount. With tabs, the prefixes will often “eat into” a certain amount of the first level of indentation. You can end up with the first level of indentation being shorter than the rest.

        (Not to mention that tab-width may vary between different tools outside of just the editor or IDE and it can be a pain to try to get them all to be consistent. The terminal I use, for example, aligns tabs to multiples of eight spaces and has no configuration to change this.)

      3. 4

        I’m sorry – but tabs are in fact defined as 8 spaces, for all practical purposes. Look at your code with cat. Or more, or less, for example.

      4. 5

        I don’t know why

        Assuming you’re saying this earnestly and legitimately do not understand, then I can share why I don’t generally use tabs:

        • One exception: if tabs and indentation are managed by an auto-formatting tool, then I generally don’t have a problem with them.
        • In projects without an auto-formatter that used tabs, they seem to always wind up being a mess. By “mess” I mean that if your tab width isn’t set to the one used by the author, then the indentation looks totally wrong. Either that, or they didn’t mix tabs and spaces correctly.
        • Code isn’t exclusively viewed in your editor. Sometimes it’s viewed on GitHub where changing the tab settings is not possible (or, is at least not straight forward).
        • Tabs means each person has their own tab width. And that means each person experiences a fixed column limit in a different way. e.g., If I use two-space tabs, then I’m going to be able to fit a bit more code in 80 columns than my co-worker who is using eight-space tabs. And now that means my co-worker is going to see long lines.

        Overall, tabs just end up being a mess in my experience. If you’ve found a way to work with them in a consistent way among your collaborators, then all the power to ya, but I haven’t figured that out. So that’s why.

      5. 3

        As a side-note, use spaces for alignment (e.g. multiline function arguments).

        I avoid doing alignment like this because it has to be done the right way lest it look right to me and wrong to you. Instead, parameters in a multiline call just get extra indentation. If you put the first argument on a new line too and maybe treat the parens like braces, this can be aligned, readable, and work for any indentation method. Maybe that’s the kind of thing you meant by:

        In the ideal case, your code-formatting then shouldn’t depend on the number of spaces per tab.

        The twist: My projects, though they would be amenable to tabs, use spaces and always have. I imagine it’s just the environment I landed in when I started my career. I don’t really think about it. But that’s the benefit, right? You don’t have to think about the pitfalls of mixing two kinds of space character when there is only one kind of space character.

        1. 1

          This is the default style in Rustfmt (indent_style=“Block”), and it’s also common in Python.

          I think this is the more sensible indent style, objectively speaking.

          Every day, I wish clang-format had an option for it (oh, how I hate clang-format).

      6. 2

        I always strive for code consistency, even when I dislike like the particular style, but using spaces for indentation is something I can’t ever get into, and will refuse to work on. Fortunately, tabs are standard for the languages I use, but sometimes I veer of into another language which uses space, and it’s painful…

        As a side-note, use spaces for alignment (e.g. multiline function arguments). In the ideal case, your code-formatting then shouldn’t depend on the number of spaces per tab.

        If you want to do that, you can do that, and ideed that’s what gofmt does for struct field alignment, however note that code will be misaligned if you use a proportional font. Yes, we do exist. No, I will not use a monospace font.

        Speaking of line length, I try to keep line length reasonable, and a quick query shows that 99.3% of my lines are under 80 columns, however, If I need a longer line, I will write a longer line! Artificially breaking the odd long line is a mistake. Not only that artificial line breaks are harder to read, but they also break grep and diff.

      7. 1

        There’s no place anywhere where a tab is “defined” as an 8-space indent.

        Very little software even defaults to 8 these days. Just terminals

      8. 1

        Two words for you: Python. And, um, well, maybe it’s just the one word.

        Python (and any language where indentation carries syntactic meaning) has a more nuanced definition of tabs and spaces out of necessity.

        See Python’s lexical spec:

        Tabs are replaced (from left to right) by one to eight spaces such that the total number of characters up to and including the replacement is a multiple of eight (this is intended to be the same rule as used by Unix).

        So, in Python’s case, tabs are defined as an 8-space indent, sort of. That is, Python has “tabstops” every 8 characters, and a tab character will take you to the next tabstop. And apparently that’s based on a Unix standard, but I haven’t bothered to research and verify that.

        What’s the big deal, then? People should still be able to just use only tabs, right? Well, then you run into the “8 spaces” thing, and your code no longer fits in your window. Not to mention that the Python style standard says “4 spaces” for indentation, which can’t be done with tabs alone.

        But everyone should configure their editor, right? Well, that works fine if you’re always in complete control of your programming environment and you only have to set it up once. But if you’re on contract and you need to use client hardware, or if you need to edit a file on a server, or if you need to ever pair program at all, then using only-tabs won’t save you from the very-hard-to-read 8 spaces problem.

        Python’s not the only language where indentation matters. Elm, CoffeeScript, haskell and elixir all have syntax-important indentation. Also Makefiles, which you may have to deal with regardless of your implementation language. They don’t all have the same complicated ruleset that Python does, but unless you’re looking up the lexical definitions, you don’t know.

        Which means people rely on the provided configurations for editing languages like that, because those configuration authors have probably checked and made sure things work. Which leaves you with whatever spacing that author used. Unless you want to learn elisp or vimscript or whatever other configuration language your editor has.

        Basically, your approach would be great if we were inventing programming from scratch. But we’re not, and the last time we did we made whitespace relevant because of punchcards, so we have to live in a world where your approach only works for a subset of situations and a subset of programmers.

    4. 8

      It’s interesting to me that things like column width and spaces vs. tabs are considered “debates” or worthy of “controversy”. Trivially, these are matters of opinion and we’ll never agree on what’s “best”. Best for you is not best for me. And best for me is not best for you. Is it so hard to accept that our personal philosophies about code readability are not universal?

      What’s more important is that code formatting is project-idiomatic. Apply the rules of the road and never debate their application. Do debate with your teams what the rules of the road should be. Not once a week, but at some reasonably long interval, in open forum. Those debates result in linting rules and .editconfigs. The rules will not be “best” for everyone – accept that from the outset – but, they’ll probably be good enough for most people. Of course the rules won’t be perfect for everyone, and the rules may even feel hostile to some. Those folks should customize their editors to display the rules of the road in a way that’s ergonomic for them.

    5. 7

      Can we just stop storing programs as 1-dimensional strings of ascii, and then all this stupidity will go away, everybody can project it however they like locally.

      1. 1

        A thousand times yes!

    6. 7

      This can’t be very controversial, the Linux kernel source guidelines are similar

      https://www.kernel.org/doc/html/v4.10/process/coding-style.html

    7. 4

      As I have done embedded development, using 80 columns is ideal because you can develop or make changes easier on the embedded device.

    8. 3

      I’m inclined to set no column limit at all. Code editors are good at soft wrap. Hard wrapping is an arbitrary task I’d rather not bother with.

      I liked this article’s point about diff quality. Splitting code onto more lines does mean higher-resolution diffs. But either that’s a human task or you automate it.

      If you automate it, you get multi-line statements and conditionals, which can yield diffs that mismatch similar segments of code. Higher resolution is not necessarily higher quality. It’s like the way a camera with more pixels for the same sensor size yields a noisier image when there isn’t enough light for each pixel. Arbitrary limits invite arbitrary solutions with arbitrary downstream effects.

      A human might have instead made a local variable, splitting not just to two lines but two statements of one line each. That will diff better. But that’s still just good coding practice regardless of line length.

      I want my team to split statements because fewer steps per statement are easier to understand. I don’t want them to split lines because a tool told them to stop thinking about the program and do some typesetting.

    9. 2

      I can’t read a rant about things like this without dropping a reference to editorconfig. That plus some CI tools that ~enforce its use alleviated so much come review time that we made it a part of our base repo templates. Automate away the low-effort arguments, reserve review brain time for complex analyses, responses, and rework.

    10. 2

      This terse style leads to terse variable names. For example: posp, patternp, opos, buf, pat, … Is there an objective argument to prefer “opos” to “positionOffset”? (I’m guessing the meaning) Avoiding abbreviations can avoid bugs due to misunderstandings.

      Another example:

          pat->content.CharRange.ptr_c =
              (char)(pat->content.CharRange.step +
                   (int)((unsigned char)pat->content.CharRange.ptr_c));
      

      If you keep it in a line, the editor can wrap it if necessary:

      pat->content.CharRange.ptr_c =  (char)(pat->content.CharRange.step + (int)((unsigned char)pat->content.CharRange.ptr_c));
      
    11. 1

      I would be all about long narrow code if we had different screen ratio conventions as to accommodate longer narrower code. Most screens today are of a 16:9 ratio, which rotated 90 degrees is ridiculously narrow and useful for nothing else.

    12. 1

      Tab indentation, tabs displayed as 4 spaces, 132 column target.

    13. 1

      This problem is especially visible when you boot FreeBSD or Linux on a 80 columns console without any framebuffer addons or other other then ‘plain’ resolution.

      No matter if FreeBSD, Linux or just a CLI tool I really respect and admire people that ‘FIT’ in these 80 columns.

      I also always try to fit in 80 columns with my scripts and always to go to newline if I am sure that 80 columns will not be enough.

      1. 1

        source code formatting != tool output though

        1. 1

          I was probably not specific enough - I was thinking about messages on the terminal displayed by the script - not the width of the code of the script.

          For example ERROR/WARNING messages from my beadm(8) script:

          % grep -E 'ERROR|WARNING' misc/git.beadm/beadm
            echo "ERROR: beadm works on FreeBSD 8.0 or later"
                echo "WARNING: Failed to update GRUB configuration"
              echo "ERROR: Boot environment '${1##*/}' does not exist"
              echo "ERROR: Can not create boot environment with '${NAME_NEW}' name"
                echo "ERROR: Can not copy current '/boot/entropy' file"
              echo "ERROR: Can not generate new '/boot/entropy' file"
                      echo "ERROR: Child snapshot '${FS}@${SNAPSHOT}' does not exist"
                          echo "WARNING: Can not bring back original '/boot/entropy' file"
                echo "ERROR: Snapshot '${1}@${2##*/}' already exists"
                    echo "WARNING: Can not bring back original '/boot/entropy' file"
                echo "ERROR: Cannot create snapshot '${1}@${FMT}'"
                    echo "WARNING: Can not bring back original '/boot/entropy' file"
                echo "WARNING: Can not bring back original '/boot/entropy' file"
            echo "ERROR: This system does not boot from ZFS pool"
            echo "ERROR: This system is not configured for boot environments"
            echo "ERROR: ZFS boot pool '${POOL}' has unset 'bootfs' property"
                    echo "ERROR: Boot environment '${4}' already exists"
                      echo "ERROR: Cannot create '${2}' recursive snapshot"
                      echo "ERROR: Unable to unmount boot environment '${2}' mounted at '${MNT}'"
                      echo "ERROR: Cannot activate manually mounted boot environment '${2}'"
                    echo "ERROR: Cannot create '${TMPMNT}' directory"
                  echo "ERROR: Failed to activate '${2}' boot environment"
                echo "ERROR: Cannot destroy active boot environment"
                      echo "ERROR: Snapshot '${2}' is origin for other boot environment"
                echo "ERROR: Cannot create '${ITEM}' snapshot"
                echo "ERROR: Boot environment '${ITEM}' already exists"
                echo "ERROR: Boot environment '${3}' already exists"
                echo "ERROR: Cannot create '${TARGET}' mountpoint"
                echo "ERROR: Cannot mount '${2}' at '${TARGET}' mountpoint"
                      echo "ERROR: Cannot create '${TARGET}${MOUNTPOINT}' mountpoint"
                      echo "ERROR: Cannot mount '${FS}' at '${TARGET}${MOUNTPOINT}' mountpoint"
                      echo "ERROR: Cannot umount '${FS}' dataset"
          
    14. 1

      But only for code, not for commit messages I assume? Or is there a good argument for limiting commit messages to 80 columns too? It’s enforced at my job but I can’t think of any good reason for it.

      1. 3

        Absolutely:

        From Linus:

        https://github.com/torvalds/subsurface-for-dirk/blob/a48494d2fbed58c751e9b7e8fbff88582f9b2d02/README#L88

        Another good explanation:

        https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html

        TLDR: If you use git in a terminal, viewing logs of properly formatted messages is much nicer.

        1. 3

          I do see that both offer advice to manually wrap the text within less than 80 characters, but in both cases the only reason given is “it looks nice with git log”.

          When I git log in the terminal (macOS), commit message bodies that are not manually wrapped are auto-wrapped within the window bounds, albeit per character and not per word, which I consider a limitation of the terminal and not of the rule of thumb.

          GUI tools such as Tower properly wrap commit message bodies per word, like any other prose.

          1. 2
            1. 2

              Thanks for that link!

              And the tool you use to visualize things cannot know.

              I would argue that tools know how to wrap common prose very well. Text editors have done this for at least 30 years.

              However:

              Some things should not be word-wrapped.

              What if a (part of a) message is not common prose? For code, you’ll manually wrap it to never go outside the screen width, so auto-wrapping should never affect code. Indeed, Linus refers to:

              They may be some kind of quoted text - long compiler error messages, oops reports, whatever.

              If I understand correctly he says that having automatic word wrap is not nice when a quote is better left in a single long line and you want it to go off-screen, typically a log message. I can see how in this exceptional case you don’t want to your tool to auto-wrap.

              However this is an argument to not uniformly enforce an 80 character limit.

              With any kind of enforcing, you’d need to make exceptions for these log lines. Perhaps by allowing markdown and making an exception for code blocks? But if you want to go that far, I would argue it would be equally involved to look for a message viewer/editor that knows how to exempt certain annotated lines from auto-wrapping instead.

              Taking Linus’ points into account, so far I would conclude that enforcing an 80 character limit on commit messages is never a good idea:

              • If a message is common prose, any tool can properly auto-wrap it.
              • If a message is not common prose, it is either:
                • Code, which we want to manually format to never reach the screen limit so auto-wrapping should never affect it,
                • A special case where a line needs to extend beyond the screen limit. If we want to account for this, we need to invest in more advanced tooling anyway because a fixed 80 character limit won’t work. In this case we get a higher benefits by configuring a message viewer that knows how to make an exception for these long lines and auto-wrap the rest.
              1. 1

                So yeah, as Linus says:

                Sure, the alternative would be to have commit messages be some non-pure-textual format (html or similar). But no, that’s not how git does things.

                You are basically arguing for markdown or “non-pure-textual format”, which is reasonable. The point is, hard wrapping and a 72 column limit is still the best option given that git is pure text, and that this is unlikely to change.

                With any kind of enforcing, you’d need to make exceptions for these log lines.

                Yes, this is annoying. It’s a wart of the pure text solution. But the alternative (throwing out line length standards for commit messages) is worse imo.

                Also, note that offloading soft-wrapping to editors or terminals is not as well supported as you’d think. While every editor/terminal can soft-wrap at the window’s right margin, most cannot soft-wrap at a specific column width. For example, in a full-screen window in nvim or Terminal, I can’t (afaik) make it soft-wrap at 80 columns. So if I don’t want to read long horizontal lines, I am forced to resize the window itself to make the not-hard-broken lines readable. This sucks.

                1. 1

                  Wouldn’t you agree that given pure text, the following holds for any (part of a) message:

                  • If it is common prose, any tool can properly auto-wrap it. EDIT: except for cases like suspending vim after working in a multi-column layout or maybe working in a fullscreen terminal window but still wanting an 80-character limit.
                  • If it is not common prose, it is either:
                    • Code, which we want to manually format to never reach the screen limit so auto-wrapping should never affect it, or
                    • A special case where a line needs to extend beyond the screen limit. With pure text there no solution to accommodate this and auto-enforce an 80-character line limit.

                  So I would conclude that the only reasons to enforce a manual / hard-wrapped 80-character width for commit message bodies, the subject line is different, are rather exceptional scenarios where the tool setup does not (always) support auto-wrapping prose to a desired line length.

                  The latter may well be an argument to keep this rule, but I think it might be worth doing a poll of how many people within the organization actually use tooling that have this limitation.

                  1. 1

                    If it is common prose, any tool can properly auto-wrap it. EDIT: except for cases like suspending vim after working in a multi-column layout or maybe working in a fullscreen terminal window but still wanting an 80-character limit.

                    This is the incorrect assumption imo. The problem is that soft-wrapping, as a feature, is typically coupled to window width.

                    As I noted in my last response, vim cannot soft wrap at a specified column length – only at the the window’s edge. Thus I can only “properly auto-wrap” by controlling window (or buffer) size, which is an unacceptable proposition. The bad case is not limited to suspending a split-window vim and dropping back into terminal (though that’s a good example). It includes closing one of my vertically split-window buffers so that the remaining buffer now fills the screen, or resizing my window for other reasons, changing my columns-per-character when I change font size, and on and on.

                    Mac Terminal itself (afaik) similarly lacks a configuration for soft-wrapping at a column width (regardless of window width). I don’t know about iTerm, but I suspect the lack of this feature is the norm rather than the exception in most tools and editors.

                    A special case where a line needs to extend beyond the screen limit. With pure text there no solution to accommodate this and auto-enforce an 80-character line limit.

                    Agreed. And it’s a problem because if you want the 80-char rule, it’s a lot better to enforce it at the CI level. I would be in favor of a simple GH action, say, that does enforce it and allows some simple escape hatch like surrounding the exceptional lines by --- or a # linecheck-disable comment or some such. It wouldn’t be hard to write one. Of course we’ve now broken “pure text” and introduced our own (albeit tiny) markup language. But “lesser of evils” is the best we’re going to get here, I think.

                    The latter may well be an argument to keep this rule, but I think it might be worth doing a poll of how many people within the organization actually use tooling that have this limitation.

                    I think this affects almost everyone who prefers reading prose at reasonable widths and also uses full-width windows sometimes.

                    As a side note (not saying this is an issue for you), the hard-wrapping requirement is hardly an inconvenience if you have a hotkey for doing it in your editor. It would be quite annoying otherwise.

                    1. 3

                      This is the incorrect assumption imo. The problem is that soft-wrapping, as a feature, is typically coupled to window width.

                      As I noted in my last response, vim cannot soft wrap at a specified column length – only at the the window’s edge.

                      Maybe this is getting a bit off-topic, but this has annoyed me for years. There is no good modal editor for prose (that I know of) and this is one of the problems of using Vim/Neovim for normal writing. People try to hack around it with plugins like goyo that create a lot of empty buffers around your document, but that has limitations.

                      Not that I have time to work on it, but every now and then I get the urge start writing a new editor from scratch for this purpose.

      2. 2

        I believe I’ve heard the argument that if you need more space to describe what you changed, you should break it into smaller commits.

      3. 1

        typical style for commit messages (in git) is a subject line of up to 50 characters, then a blank line, then a multi-line description no more than 72 columns wide.

        1. 2

          Do you have any argumentation for why you wouldn’t want commit messages to be word-wrapped automatically by the tool you are using to view or edit them?

          1. 3

            A short subject line (50ish) allows viewing and skimming commits, one per line to see what has been done.

            1. 1

              That’s a good point for subject lines. I’m not sure if there would be an easy way to enforce a size on the first line only…

          2. 2

            nearly every UI that displays a list of commits will have a layout that is optimized for subject lines of 50 chars or less. Beyond that, whether the first line will be trimmed or wrapped (and at what position it will be trimmed/wrapped) will vary substantially from client to client. The web views in github and bitbucket work very consistently when this rule is followed, but not as consistently when it isn’t. git log --pretty=oneline also benefits tremendously from this rule of thumb since every line also includes the full commit hash, which is 40 chars wide.

            1. 1

              Thanks for these pointers. Indeed for the subject line a limited line length seems very useful.

              This does not answer the question why the body of the commit message should be hard-wrapped at 80 lines as well though.

              Again, I can imagine that it is hard develop a git hook to consistently enforce that only the subject line has a limited length. But although I may be missing edge cases, it doesn’t sound impossible either.

              1. 2

                git log will indent all lines with 4 spaces. when it softwraps because the terminal isn’t wide enough, the wrapped lines wind up unindented. If you have any line breaks at all, you’ll wind up with mixed indentation levels.

                a pre-commit hook is still opt-in and client side, so it’s not really enforceable if you’re using some sort of star topology like github/gitlab/bitbucket/etc, which is how the majority of projects and teams use git. Most providers of git servers don’t permit custom pre-receive hooks, since you’d have to allow the execution of arbitrary code. For github, it’s an enterprise feature. Rejecting PR’s in CI is pretty common but generally toolsets expect that rejected PR’s get updated and eventually merged, not deleted entirely. You can rewrite history in PR’s in most toolsets but the experience is often lackluster.

                1. 1

                  That is a good point, if your commit message relies on indentation, auto-wrapping will not work for it. However as far as I can see, typical prose will not depend on indentation, right?

                  A pre-commit hook backed by a blocking CI rule is what we use now to enforce the 80 character limit, this seems to work pretty well so far. Indeed rewriting history is the common approach here. As far as I have experienced, github PRs deal with that pretty well.

          3. 1

            Pretty much for the reason Daniel gave in the post: humans typically struggle with long lines. If I run git show on a commit and my terminal happens to be quite wide, git won’t reflow the text for me (and nor should it). Hard breaks in the commit message mean that everyone reads the commit message the same way.

            1. 1

              That’s interesting, so there are scenarios where you have a wide terminal window but you don’t want wide lines? Wouldn’t it be more convenient to size the terminal window to the width of your personal preference and have the lines adapt?

              1. 1

                so there are scenarios where you have a wide terminal window but you don’t want wide lines?

                Yes. I typically have the terminal wide so that, for e.g. in vim I can have a vertical split with two files open side by side.

                Wouldn’t it be more convenient to size the terminal window to the width of your personal preference and have the lines adapt?

                For some cases, yes: e.g. when scanning through log files I’d prefer it to wrap (journalctl’s default of chopping rather than wrapping is maybe the most annoying thing), but for my use-case above I really do want a wide terminal with two (or more) files open with narrower text; but when I suspend vim to commit changes or review commits, I don’t want the commit messages filling the entire width of the terminal. I just can’t read long lines easily like that.

                1. 1

                  in vim I can have a vertical split with two files open side by side.

                  But wouldn’t vim be able to wrap lines for every individual column in this case?

                  1. 2

                    Yes, but:

                    I suspend vim to commit changes or review commits, I don’t want the commit messages filling the entire width of the terminal.

                    And sticking to a relatively fixed line length means as I add or remove splits, the code isn’t reflowed, so I remain looking at the same things and don’t lose context or focus by having to figure out where things moved in a reflow.

                    1. 1

                      I see, so we can conclude that there are certain scenarios in which (a specific use case of) the tooling is not able to auto-wrap prose reliably.

                      1. 1

                        I think it’s fairer to say there are cases I’d prefer not to need tooling to auto-wrap. Not just prose; prose and code.

                        1. 2

                          That’s indeed a better way to put it, thanks for refining.