The git history command

(lalitm.com)

340 points | by turbocon 11 hours ago ago

210 comments

  • bad_username 6 hours ago ago

    I was uncomfortable with git until I read (the first 3 chapters of) the pro git book ( free here : https://git-scm.com/book/en/v2 ). It provides a great mental model of how git works under the hood. The UI of git - for better or worse - directly reflects its internals. And when I understood them, everything clicked into place.

    • Hendrikto 3 hours ago ago

      Git is not nearly as confusing as people make it out to be. They just never take the few hours it takes to understand it. Which is a sad state of affairs for such an essential tool in the belt of any software engineer.

          git commit -am “Changes”
      
      just does not cut it, if you call yourself a professional.
      • hackrmn 2 hours ago ago

        My observation has been that those who have never learned Git properly -- disregarding for a moment the issue with what "properly" means here -- just don't think they need to, sticking to very simple workflows that produce linear graphs featuring squash-rebased work throughout. Because they don't know Git's fundamental model (including what you'd think was the obligatory piece of information that commits are essentially immutable), they don't venture farther than their confidence suggests, keeping it within the circle so to speak.

        The tragedy, if you ask me at least, is rather that they then start imposing the "keep it simple" culture onto everyone else, which frankly turns Git into what SVN and CVS were accomplishing before it, with all the drawbacks of those. This keeps 90% of the team satisfied 90% of the time because there's nothing wrong with strictly linear graphs and the pro's that are asked to produce these, can always squash-merge their intricate local development history before they push to Github (which some Git users also think is part of Git proper).

        Something about using Git in the aforementioned way just bugs me strongly. I admit it's a me problem, very likely, but lately I've also had to admit that it's not just that either.

        For instance, if I need to fix a bug I use `git blame` to find the commit where I have learned the bug originated. I do a `git checkout -b ... <commit>` to start working on a fix, creating a branch starting at the problematic commit. Already that is head and shoulders above what many people I work with do or know _what_ does (or why would one want to do that).

        I do it because it creates a _trail_, certainly more so than just committing on top of `master`, even with a good commit message.

        But my practice doesn't produce linear graphs, even as pushed to Github (which we have to use, for better and for worse) and shared with everyone. I then get people coming to me and complaining they can't merge and it becomes obvious they don't understand Git sufficiently to do anything else but `git reset --hard` or worse, `rm -rf * && git pull` and hope for the best.

        Not sure where I was going with this, something about why use Git when it's the new SVN with everything SVN had and none of what SVN didn't have...

        • nixon_why69 an hour ago ago

          Ok but the final outcome, most of the time, is a linear graph unless you're maintaining extremely long-lived branches for some reason.

          Setting practices so that linear graph will be easy to understand in history is still a good idea, no? I'm not religious about squash-merge on master but when I look at master's history, I'd expect each individual commit to have a good message and be releasable.

          • hackrmn an hour ago ago

            A linear graph doesn't do any developer in the team except Github (which isn't a developer in this context) any good because they have to pull down the graph at some point and when they have to fix something, although they will be able to track the blame to some commit in the middle of the graph, when they fix it and merge it it has to be squashed again (by hard or soft enforcement), which like I said negates much of the point with Git -- there's no usable history left.

            Point being that branches aren't something to avoid, implying that complicated graphs are not to be avoided either, but embraced and knowing how Git works it's not a problem at all (unless your "bush" is accidentally complex in a bad way) -- except that if noone bothers to learn Git, it _becomes_ a problem, solved at the cost of the value that Git provides -- branching (not just ephemeral branching for your local convenience). Exacerbated by Github since everyone pulls from there -- meaning that production-grade code is not a true graph but a linked list, on average.

            • nixon_why69 an hour ago ago

              > the value that Git provides -- branching (not just ephemeral branching for your local convenience).

              I think this is the disconnect. I could see big libraries maintaining branches for each major release and I understand why linux does it. But if I'm maintaining FooService at work then I actually do just want a linear graph of all the commits that have been in production, in commit order.

              • hackrmn 27 minutes ago ago

                If you want that, mandate developers use prefixes like `!fixup` and do `git rebase` _on your end_ -- why force upon everyone your ideas especially if it also squashes all development history? This also removes development friction because people can work with Git on their end the way they like without regard to some convention that can be avoided -- save for the "!fixup" thing which can be considered useful metadata.

      • kreco 2 hours ago ago

        > Git is not nearly as confusing as people make it out to be.

        The people are confused, it's a fact. So it is confusing. Stop gaslighting people.

        • xelxebar an hour ago ago

          Interesting. "A is X" is different than "I experience X from A". The former employs an objectivist lens while the latter a subjectivist one. I have had the pleasure of witnessing debates about whether a room really, truly is cold or not, which all resulted from a simple "it is cold in here" comment. In my experience modern English speakers tend to bias toward the objectivist register while Japan tends the other way. One of the joys in my life is how absorbing languages and cultures elucidates previously-unperceived distinctions. This discussion makes me want to try picking up Ithkuil again.

          /r

        • ninkendo 2 hours ago ago

          There’s this important word in the sentence you seem to be ignoring: “as”

          GP isn’t saying “git isn’t confusing”, they’re saying “git isn’t as confusing as people make it out to be”

          The point being, people exaggerate git’s confusingness when discussing it. There’s an element of irrationality here that’s worth bringing up, especially when it comes to comparing it to competing software. Once it has a reputation for being confusing, you’re more likely to be scared of certain workflows, you avoid them, and the problem compounds. Similarly if a VCS has a reputation for being “simple”, people might gravitate to it, learn it first, then parrot conclusions that git is too complicated because they never really gave git a chance in the first place (often they do take the time to read the other VCS’s documentation, and if they would have done the same for git they would have had no problems.)

          It doesn’t help that there are so many bad tutorials out there that simply give you what commands to run, and tell you dumb stuff like “just make another clone if you get stuck”, and that makes the problem so much worse, and isn’t git’s fault.

          Git is a bit confusing sometimes, but it’s mostly for reasons like “the reset and checkout commands do too much”, and “some low level commands are easy to confuse with high level commands” not because it’s a fundamentally confusing tool.

          • kreco an hour ago ago

            > Similarly if a VCS has a reputation for being “simple”, people might gravitate to it, learn it first, then parrot conclusions that git is too complicated because they never really gave git a chance in the first place (often they do take the time to read the other VCS’s documentation, and if they would have done the same for git they would have had no problems.)

            I don't think I need to reply to a comment that illustrate the main point of this sub thread.

            • ninkendo an hour ago ago

              You just did though…

              Maybe try and explain in more than one-sentence quips why you think git deserves its reputation? Otherwise you’re just coming off as a bit of a troll. Have a nice day.

        • xeyownt 2 hours ago ago

          If you ignore gravitation, a sphere earth can be very confusing.

        • dspillett 2 hours ago ago

          But not as many people are as confused as is sometimes made out. And those who are confused are not as confused as people make out¹. Implying that a great many people are very confused because some are is far more gaslighty than suggesting it isn't that hard in the majority of circumstances, IMO.

          --------

          [1] many (and I'd include myself here) are fine using the basics, perhaps with some less as-simple-as-possible workflows, but might need to scan the docs if they hit a conflict merging two branches that have developed independently for a fair few commits and have overlaps

        • Thanemate 2 hours ago ago

          >The people are confused, it's a fact. So it is confusing. Stop gaslighting people.

          I don't think this sort of aggression is warranted, as the fact that I find something confusing doesn't directly imply an intrinsic feature of the object that I'm confused with. One can reach that conclusion by observing that, not everyone who learns about the object finds it equally confusing.

          All that to say: "The people are confused" doesn't mean that "All people are confused".

          • kreco 2 hours ago ago

            There is no aggression.

            If your product has a reputation to confuse users compared to other products, your product confuses users.

            Let's not start to bend reality just to back up some narrative because after reading a N hours documentation everything is OK.

            • dspillett 2 hours ago ago

              > Let's not start to bend reality just to back up some narrative because after reading a N hours documentation everything is OK.

              If you expect everything to be as easy as pie without needing to make a little effort to read a bit of documentation, then perhaps the problem is not the product but the fact that you are in the wrong industry, or the wrong role within that industry, for you. Have you considered a management track?

              Git is intended to make certain patterns possible, and practical. “Easy for people won't read some documentation” was never one of its design goals.

              • kreco 2 hours ago ago

                You conveniently cherry picked the least relevant part of my message.

                No one said everything should be easy as pie.

                There are other software similar to git that have not such reputation. Version control is not new.

                • account42 an hour ago ago

                  > There are other software similar to git that have not such reputation. Version control is not new.

                  Yes, there are alternatives that aren't used by anyone except dedicated fans. If they had the wide user base that git enjoyed you'd hear just as many complaints about them.

                • jamesnorden an hour ago ago

                  Because people actually use Git instead of whatever you mean.

                  • kreco an hour ago ago

                    This is irrelevant to the topic.

                    I didn't ask why git was widely used. I didn't say git was useless.

                    Again, there were version controls before git came out.

                    • echoangle an hour ago ago

                      I think the point was that a lot of people are confused by git because a lot of people use it. Meaning that the other software where people don’t complain would get the same amount of complaints if it had as many users as git has.

            • ninkendo an hour ago ago

              > If your product has a reputation to confuse users compared to other products, your product confuses users.

              Is your contention that all reputations are deserved, by definition? That’s certainly an interesting take. It leaves zero room for the concept of an “unfair reputation” for example. Maybe you should rethink your argument here.

    • hnfong 5 hours ago ago

      Same here. The git commands were confusing to me until I actually saw a Linus video on youtube explaining how the git data structures worked under the hood. It was dead simple, and one could easily mentally map the tools' functions onto how they operated on the data structures.

      Once I understood that, as you said, everything clicked into place.

      Somehow the "higher level abstractions" that git tries to do makes the things ever so more confusing.

    • xyzsparetimexyz 5 hours ago ago

      No it doesn't. Half the git commands are low level, half are high level. It's not 1:1 at all.

      • palata 5 hours ago ago

        So when someone tells you "understanding X helped me a lot", your answer is "no, it did not"?

        > It's not 1:1 at all.

        I don't see any mention of "1:1" in the parent.

        • debugnik 5 hours ago ago

          They're replying to

          > The UI of git - for better or worse - directly reflects its internals.

          • palata 2 hours ago ago

            > Half the git commands are low level, half are high level.

            Can't we say that the low level level commands reflect its internal? ...

        • jesse_ash 5 hours ago ago

          > The UI of git directly reflects its internals

          Maybe?

    • vasco 5 hours ago ago

      Mercurial had by far the best UX, never had to read anything to learn it. I just pretend that I'm using mercurial when using git and nuke local repo if I mess up. Been doing it for my whole career.

      • black_knight 4 hours ago ago

        I love darcs! Somehow its interface just vibes with me. It is interactive by default, and the commands like “record”, “rollback”, etc, are somehow intuitive. Darcs also tried to put more semantic content in the patches, like file operations or search replace parches.

        It is always satisfying to rename something, then merge in some work where someone used the old variable name in the meanwhile, and the merge would go through automatically applying the rename!

      • yurishimo 4 hours ago ago

        I've often found that many problems when working in teams can be traced back to `rebase`. I understand the benefits, but if you're already working on a team where history is not used in any serious way, then you cut out a lot of foot-guns by only using `merge`.

        • Hendrikto 3 hours ago ago

          > if you're already working on a team where history is not used in any serious way

          Then you are doing it wrong. Sadly this is very common.

        • zwischenzug 3 hours ago ago

          Except the "merge mess" footgun.

          I got into training people in Git (I now do it for O'Reilly) because I worked with 12 teams that merged _everything_ into sub-branches. The result was that the `git log --oneline` command resulted in screensful of just pipes.

          My initial training goal in training was getting my students to understand a rebase to avoid that mess.

  • jolmg 10 hours ago ago

    > scary rebase -i commands that can leave your tree in a half-broken state if you so much as sneeze

    `git rebase --abort` exists. One can also set a tag or something before doing the rebase, do whatever, then `git reset --hard $set_tag` to go back. Nothing to be scared of. Not like the prior state is lost.

    • account42 an hour ago ago

      You don't even need to set a safety tag like that anywhere in git, the reflog does that for you automatically.

    • rmunn 10 hours ago ago

      I have so many branches named `temp` or `before-rebase` for exactly that reason; I'm using them effectively as tags, but branches can be moved around with less ceremony than tags (since tags are designed to be for things like v1.2.3, placed once and then almost never moved again), so I usually just do `git branch before-rebase/some-feature` before running a big `rebase -i`.

      I've almost never needed to run `get reset before-rebase`. But I have often done `git log -p before-rebase` and compared that to the post-rebase state of the branch, to ensure that the merge-conflict resolution(s) that came up during the rebase haven't accidentally introduced an unintended change.

      • chrismorgan 8 hours ago ago

        Diffing diffs is so valuable for that reason, seriously underrated. Once I even found a use case for diffing diff diffs.

        I also often wish to edit commits or resolve rebase conflicts or whatever by editing the patch rather than the files.

        • amarant 5 hours ago ago

          Hey yo,I heard you like diffs, so I put some diffs in your diff so you can diff your diff while you diff!

          Sorry, couldn't resist. The xzibit was too strong in your comment.

      • bjackman 4 hours ago ago

        After a rebase, mybranch@{1} refers to the previous location of mybranch, so you don't need to manually track these before-rebase branches etc.

        (In practice I find this syntax super annoying and usually end up typing `git reflog mybranch` and then copy-pasting the commit hash from the output).

      • jolmg 10 hours ago ago

        > but branches can be moved around with less ceremony than tags

        `git tag -f` to move a tag.

        Personally, I just do `git show` when I'm feeling cautious, but I can generally just scroll up to find the last `git commit` I did with the hash in the output. `git reflog` should also have record of it, so everything else is kind of extra.

        • rmunn 10 hours ago ago

          Good point, that's no more ceremony than moving a branch. I guess I've just gotten "branches are movable tags" so deep into my hindbrain that I absorbed "tags are hard to move". But that's not actually true, and for what I'm doing (save this point in history for a while) a tag makes slightly more sense, semantically, than a branch.

      • hack1312 6 hours ago ago

        This is the exact same thing I do, though with the prefix "pre-rebase/"

    • catlifeonmars 10 hours ago ago

      Do you use git reflog?

      • jolmg 10 hours ago ago

        One can also use that, or just `git log -n1` and taking note of the commit hash. So many options.

        • jmholla 7 hours ago ago

          Fun fact: you don't even need the `-n`. `git log -1` does the same thing, for any number.

              -<number>, -n <number>, --max-count=<number>
                  Limit the output to <number> commits.
      • ibizaman 6 hours ago ago

        I do when I forget to run the git branch comment before. But I find it still hard to understand exactly which commit to reset to in the reflog.

        • _ikke_ 5 hours ago ago

          The branch reflog (git reflog <branchname> or git log -g <branchname>) is a lot easier to follow in the case of rebase than the HEAD reflog (which gets an entry for each commit that gets checked out / applied).

    • dalmo3 4 hours ago ago

      > `git rebase --abort` exists

      Exactly. 50% of the times I type git rebase it is followed by --abort.

    • andrepd 7 hours ago ago

      No need for that even. Just git reflog and rewind back to any spot your want!

  • nativeit 10 hours ago ago

    I don’t consider myself a coder or programmer, but learning git was like an organizational superpower for my particular brain wiring. I use it for websites, design projects, electronics engineering, music composition, personal knowledge bases, remote administration scripts, config management, snippets, so many applications and so many features for one system. It’s not always perfect, but I tell everyone I work with they should learn it.

    • m463 6 hours ago ago

      I also took a leap in organization. But I don't think you're responding to git in particular, just a source control system.

      git (and other version control systems) take what you made, organize and preserve it, and you can get any number of copies at a moment's notice.

      It is good for people to be able to do work and not worry about it.

      I remember reading David Allen's book Getting Things Done years ago. It takes effort to read through his writing, but he had good ideas.

      One thing he mentioned is that you need a 'trusted system' where you can collect and organize your thoughts. It lets you offload what you're worrying about until the time you need to do something with it.

      I actually use omnifocus to do this for my tasks/projects/lists, but for what I actually do on a computer, I trust git to organize and preserve the software (and some data) I have written.

    • quacked 7 hours ago ago

      How do you use it for music composition?

      • tunesmith 6 hours ago ago

        I use it for lilypond for notation. I always considered it superior to Finale and Sibelius anyway. Not sure how it stacks up against the more modern commercial notation apps. But I love having a real trackable version history of my pieces.

        What's also cool is the more advanced llms know lilypond and music theory too, so they can do things like... I don't know, check for counterpoint errors. I've used it with limited success to expand my jazz lead sheets into two-hand piano arrangements just for practice exercises.

        • quacked 20 minutes ago ago

          I've considered using Lilypond, but I really like the autoplay feature in Musescore, as well as the lack of delay between placing notes and seeing the result.

      • knodi123 7 hours ago ago

        there are plenty of text-based digital music notation systems. Then, you commit periodically as your composition evolves, and you can have all the history/fork/undo whatever that you might want.

        • seba_dos1 7 hours ago ago

          Also, files don't have to be text-based at all to version them with Git. When you're versioning things for your own sake, there's often not much difference between keeping text and binary files there, as it's not like you'll have to resolve an unexpected conflict.

          • rmunn 7 hours ago ago

            I find it really useful to be able to diff two commits, which if you're using a binary format is only possible if you have a meaningful-diff tool for that format. Some formats have one already created, more formats don't. (Though these days, an LLM might be able to produce something suitable).

  • chandlerswift 8 hours ago ago

    I've been theoretically a big fan of these commands; I use the `jj` equivalents all the time. The roadblock I've run into is that I as far as I can tell (from the man pages and the git source code) there's no way to get `git history` commands to sign commits they modify:

        $ git log --oneline --show-signature  # look ma, I signed my commits!
        3a1dd8f gpg: Signature made Mon 13 Jul 2026 10:45:50 PM CDT
        gpg:                using RSA key FBF32CDBCC134B44FD29B66FA851D929D52FB93F
        gpg:                issuer "chandler@chandlerswift.com"
        gpg: Good signature from "Chandler Swift <chandler@chandlerswift.com>" [ultimate]
        Second commit
        03c3f6e gpg: Signature made Mon 13 Jul 2026 10:45:16 PM CDT
        gpg:                using RSA key FBF32CDBCC134B44FD29B66FA851D929D52FB93F
        gpg:                issuer "chandler@chandlerswift.com"
        gpg: Good signature from "Chandler Swift <chandler@chandlerswift.com>" [ultimate]
        Initial commit
        $ git history reword HEAD~
        $ git log --oneline --show-signature  # oops! where'd they go?
        5662b2c (HEAD -> main) Second commit
        6bf6830 Initial commit amended
    
    This has pushed me back to the time-honored `git rebase -i` since I do want to keep my commits signed.
    • jmholla 7 hours ago ago

      Woah! That feels like a huge oversight and like it bypasses standard commit logic. The man pages do say `git history` is experimental. Sounds worth a bug report.

  • jonathanlydall 4 hours ago ago

    I've been doing regular significant re-writes to my local Git commit history with relative ease for over a decade even without this new Git command.

    I'm convinced that a big part of people often finding Git and rebase difficult is a user interface issue, having to know all the correct command line options and having to make your own mental model of what's happening and what you want to do, all makes it difficult to get a firm grasp on things.

    I can't comment on what equivalent alternatives (especially on macOS/Linux as I'm a Windows user), but in terms of a UI for Git which exposes enormous power in an easy-to-use way I've found TortoiseGit to be spectacular and I especially like its rebase dialog:

    https://tortoisegit.org/docs/tortoisegit/tgit-dug-rebase.htm...

    Which you kick off from a context menu option from the commit line on the commit log you want to rebase onto with a simply named "Rebase <current reference> onto this" option:

    https://tortoisegit.org/docs/tortoisegit/tgit-dug-showlog.ht...

    It's super easy to re-order, split, combine, edit commits from here and it's obvious that will happen. If for whatever reason you decide you want to back out midway, you just abort and you're back to where you were.

    I will concede there are aspects of a TortoiseGit I find a bit annoying, particularly that I feel I have to click around too much, instead of a shell extension I would prefer an app you launch with tabs or something, but I think this is a fundamental design principle of TortoiseGit, which followed the same principle as TortoiseSVN.

    There is Git Extensions for Windows which seems nice at a glance, I tried it briefly, but I think I didn't stick with it either due to being unable to find an option I regularly used or I was just so used to TortoiseGit already.

    • Cthulhu_ 4 hours ago ago

      Same, but at the same time the existing workflow is a bit more clumsy / these commands are a bit more ergonomic.

      Fixup was already possible through `git commit --fixup`, and before that through `git rebase -i`; reword also through `git rebase -i`. I suppose the developers got enough feedback that editing a file to decide what to do with each commit was a bit frustrating for some users.

      It's a higher level command on existing functionality I suppose.

    • crabbone 4 hours ago ago

      In terms of UI for Git, I've never seen anything getting remotely close to Magit. It's both in-depth and a simplified stateful interface.

      Here's what I mean by "stateful": one of the huge problems with command-line tools is that their output becomes mostly inaccessible upon subsequent invocations. Suppose you ran git-log, and now you want to apply the knowledge gained from reading its output to your next action (say, you want to cherry-pick a commit). But you are lucky if the hash of the commit in question is still somewhere in the terminal. Otherwise... you aren't writing that from memory...

      Stateful UI to command-line tools allows multiple interactions in parallel and preservation of information obtained in previous interactions.

      Git needs a lot of state. You need to remember facts s.a. what branch you are on, what branch did you switch from, what files have been modified, what commits haven't been pushed etc. The requirement to remember all of this is overwhelming and makes the effective use of the tool difficult. This is where various tools come to help (eg. Shell plug-ins that provide auto-completion or modify the prompt to incorporate some of that state info).

      I believe that people complaining about difficulties of using Git are often handicapped in their use of surrounding tools that would otherwise mitigate the problems above: they don't know how to add Shell plug-ins that display the current branch, they don't know how to have multiple tabs/panes open in a single terminal session, how to copy text between those tabs/panes, they don't know how to invoke / search auto-complete options.

      Genuinely, if you don't have tools to help you use Git, something that people who are used to navigating the world of terminal UI, using Git becomes very unpleasant.

  • rom1v 4 hours ago ago

    > `git history fixup` fixes an old commit that has something wrong in it, then autorebases all your branches to match.

    Simplifying `git rebase -i` is a great idea, but unfortunately, that does not match my workflow.

    I always keep an history of my branches. For example, when I develop a feature, the first version of the branch is `myfeature.1`, then `myfeature.2`, and so on. This is useful because I can retrieve an old version when something behaves differently in a newer one. (And no, `git reflog` will not help)

    This has saved me multiple times. For example, I can determine that a problem was introduced between `myfeature.58` and `myfeature.59`. If the "feature" contains 15 commits, I do:

        git range-diff myfeature.58~15..myfeature.58 myfeature.59~15..myfeature.59
    
    This lets me see the changes between the 2 versions, commit by commit (even if they don't have the same base).

    I don't want all the branches containing a commit to be rebased automatically (I already try using tags for old versions instead, but this does not quite fit).

  • paxys 9 hours ago ago

    I don't get all the effort people spend in perfectly curating git history. No one is ever going back and reading individual commits. Just squash everything before merging and call it a day.

    • jxf 9 hours ago ago

      > No one is ever going back and reading individual commits.

      I violently disagree with this.

      At a minimum, when I review PRs I look at the commit history to understand what's up. If the path that was taken to commit this is full of "oops" and "fix" messages, it's an immediate reject for me. The commits tell the story and it's a kindness to your human reviewers to not make them work harder to understand the point you're trying to get across.

      • nl 9 hours ago ago

        > If the path that was taken to commit this is full of "oops" and "fix" messages

        great way to encourage people to rebase then!

      • GrandfatherTECH 9 hours ago ago

        What's up with the fix commits? Maybe I misunderstood you, but there ain't nothing wrong in fixing stuff you offer in your PR. And there can also be multiple commits even before the PR while you're developing your PR.

        • locknitpicker 8 hours ago ago

          > What's up with the fix commits?

          They shouldn't show up in the commit history. In a PR, you merge them in the commit that they actually fix. Otherwise when you use git blame to get the context of why a line of code was changed, all you see is a useless "fixup" message that is worse than having nothing.

          Anyone can do better than a fixup commit. And doing metter means merging them into the actual commits that are fixed.

          • gbalduzzi 7 hours ago ago

            > Otherwise when you use git blame to get the context of why a line of code was changed, all you see is a useless "fixup" message

            Isn't this solved if you squash the commits when merging the PR? I personally don't care that much about the commits inside a PR, the are just temporary because when a PR is merged they are squashed and you only get one commit for the whole feature on the main branches

            • NateEag 6 hours ago ago

              I once root-caused a revenue-losing bug that had the entire rest of my team stumped with ten minutes of git-bisect.

              It only worked that well because the team had all internalized my advice to write small, coherent commits, so the bisect landed on a ten-line change.

              I strongly dislike the recent trend towards squashing every branch into a single monster commit.

              • LtWorf 6 hours ago ago

                Most people who squash things have never used git bisect, cannot solve a merge conflict and when there is one will just delete the directory and clone everything again. I've worked with such people. They can go on like this for an entire lifetime.

                • user43928 5 hours ago ago

                  I used git bisect once in 10 years, and it was when I learned about its existence.

                  I am convinced that very few know about git bisect, much less use it regularly.

                  • locknitpicker 5 hours ago ago

                    > I am convinced that very few know about git bisect, much less use it regularly.

                    Yes, unfortunately not all companies have a high hiring bar. Some

                • skydhash 37 minutes ago ago

                  For me (I know you used most, not all). A PR is an atomic thing. Either one bug or one feature. Commits inside it are mostly time snapshots, and fixing formatting and linting errors. If I where to properly present the PR, it will also have been a single commit.

            • xorcist 3 hours ago ago

              > if you squash the commits when merging the PR?

              You tidy up and rebase before making a PR. Anything else is really disrespectful of your reviewer's time. That is also how all the larger open source projects operate.

              > you only get one commit for the whole feature

              If you are doing one logical commit per PR, you are doing way too many PRs.

              Alternatively you don't have a working review process.

              • account42 33 minutes ago ago

                Yes, often you have separate logical changes that should still be reviewed together.

              • skydhash 9 minutes ago ago

                Not really, because that one commit represent a logical changes to the codebase. It’s either in or not. Splitting it would be only cosmetic. That’s what a good PR in my opinion.

                Presenting a series of patches is good in an email format because when I’m adding them, I can evaluate each and decide whether I want it or not. But GitHub (and forges that copies it) is lacking in that regards without me taking over the branch.

                So the word is to make the PR the unit of changes, and only review the whole diff, not the individual commit.

            • Cthulhu_ 4 hours ago ago

              That's one approach, sure, probably works best if your units of work (e.g. everything inside of a PR) are small and atomic though.

              Other use cases exist where each individual commit adds value / changes something important / is atomic. Which one is best depends on the use case.

              What should definitely be avoided (or, what should not end up in main) is "work log" commits. Many people use git commit like a save / checkpoint operation, that's the kind of thing nobody needs to read. That's the "fix" commits.

              Succinct guideline:

              Good commits: "When applied, this commit will <commit message>"

              Bad commits: "I did <commit message>"

              Then whether it's one commit or the result of a squash merge it doesn't really matter much anymore.

            • locknitpicker 5 hours ago ago

              > Isn't this solved if you squash the commits when merging the PR?

              In theory, yes. Squashing is an extreme approach to merging fixup commits.

              It also throws the baby out with the bathwater by removing individual commits that explain and clarify how and why some changes were introduced as part or a PR.

              If your PRs are tiny and don't introduce major changes then squashing is ok. Instead, you should do the right thing and curate the set of commits featuring in your PR.

              • CuriouslyC 2 hours ago ago

                Making small atomic commits as you go in the age of AI tends not to go great because it forces too much human in the loop in a lot of cases, and the percentage of AI code rework is significantly higher than manual code, so the history tends to be harder to keep clean.

                It's ironically easier to create a messy agent work branch then have the agent cherry pick independent PRs from it into atomic commits post-work.

      • crabbone 9 minutes ago ago

        Parent doesn't have experience of working with codebases with slightly high than average code quality requirements.

        In products s.a. storage, avionics, medical appliances etc. it's very typical to have a requirement for each commit to compile and to apply tests retroactively. I.e. once a test is added against an existing feature, it is run against every commit since the feature creation (this is also why git-bisect exists).

        However, it's true that a lot of companies would probably do better with just rsync instead of Git. Their Git history is in such a bad state that it's basically useless. It just doesn't make sense to use such a complicated tool as Git to deal with the average workflow.

      • fcarraldo 9 hours ago ago

        Mine aren’t full of “oops” and “fix” messages, because I squashed them.

        • bonzini 7 hours ago ago

          So you're "spending effort in perfectly curating git history" and agreeing with your parent comment.

          • ozim 6 hours ago ago

            Just squash everything before merging and call it a day

            That is also a line from top comment. Everyone read „perfectly curating git history” and went rage commenting instead of reading and understanding what OP wrote.

            • bonzini 5 hours ago ago

              Nope. Perfectly curating history is indeed the opposite of squashing—you squash because you couldn't be bothered to curate your commits. Squashing is a workaround not an alternative solution.

      • ozim 6 hours ago ago

        But parent wrote:

        Just squash everything before merging and call it a day.

        He didn’t write „leave a mess”. So it feels you wrote knee jerk comment or just writing whatever you wanted to write disregarding whatever was written.

      • InvertedRhodium 8 hours ago ago

        Depends what the git history is supposed to show. Personally, I prefer people to leave their mistakes and reversions - though I'd require more description messages than "oops" or "fix", something that explained why it was being reverted or swapped out would be the minimum.

        Sometimes you try things one way and they don't work out, so you go in a different direction. Capturing why this happened and when can go a long way towards explaining downstream decisions that might seem confusing to someone with a fresh perspective.

        • bonzini 5 hours ago ago

          The why for a commit belongs in the message or code comments not in the history.

      • JohnMakin 8 hours ago ago

        yea I look at commits several times a week at least, especially when commits are tied to a ticketing system/project it helps a lot going back months later on a large codebase going “how/why did this change happen”

        I do tend to squash or make my entire change in one commit though so maybe I misunderstood your comment. If I have a fix commit often I’ll just tag a separate PR/ticket to keep the change history/change control clean

      • CuriouslyC 2 hours ago ago

        You sound pleasant to work with. I bet your coworkers route around you when they can, and when they can't they cherry pick from their working branch to deliver monolithic commits while rolling their eyes.

        • account42 31 minutes ago ago

          No, he sounds like a professional with standards.

          • CuriouslyC 28 minutes ago ago

            A professional with standards who wasn't also unpleasant would put the time in to review the content of the commits with a request to clean up the history. Someone who looks at the history, thinks to themselves "not how I like it" and just auto-rejects the entire PR without any further thought is just a bad coworker.

            • account42 21 minutes ago ago

              No the bad co worker is the one who is trying to offload his job on the reviewer.

              • CuriouslyC 10 minutes ago ago

                A programmer's job is to deliver business value to their employer. If you're slowing down PR turnaround by mindlessly auto-rejecting on stuff that the suits don't care about, you better have a rock solid case for why that is going to deliver business value down the line, otherwise you're actively sabotaging your employer to bikeshed your personal preferences, which is the hallmark of a bad employee.

                Rejecting an obviously bad PR after scanning the code quickly is one thing, burning business cycles on PR turnaround/latency to bikeshed bookkeeping without spending any time on the actual value producing portion of the PR is just bad. At the minimum you wasted an opportunity to give feedback on the proposed solution, thus probably necessitating another round of reviews, with the associated org latency.

      • ansgar77 3 hours ago ago

        I think that the path that was taken should include mistakes. It's natural that code at some point would contain bugs and mistakes. If anything, your approach would encourage to squash those commits into one just to make it being review-worthy, but that misses the point then.

        • account42 26 minutes ago ago

          It shouldn't be that path that was taken but the path that will be taken when the PR is merged, split up into as many self-contained steps as possible to ease review now as well as triage if problems are found later.

      • danieltanfh95 8 hours ago ago

        NGL AI usage is driven by friction in presentation and communication over petty details.

      • bobbylarrybobby 9 hours ago ago

        Do you really care if someone forgot to format before committing? They can always squash and push locally if they need to.

        • LtWorf 6 hours ago ago

          I really really really do not want the autoformatter stuff happening in the same commit as where the real thing happens. I don't care to review if the autoformatter is working properly.

        • locknitpicker 8 hours ago ago

          > Do you really care if someone forgot to format before committing?

          Not OP but yes I definitely do. If you expect others to spend time reviewing your code, you are obligated to start off by reviewing it yourself. Posting a mess helps no one and makes code harder to audit.

      • gofreddygo 8 hours ago ago

        Oh that is such a bad heuristic ! The commits and history of how a PR was put together is no indicator of the quality of the PR or the thought process that led to it. Thats the equivalent of rejecting a (handwritten) essay for having too many corrections. ridiculous.

        The code is all that should matter. Maybe comments for being nice to others and my future self. thats it.

        • locknitpicker 8 hours ago ago

          > The commits and history of how a PR was put together is no indicator of the quality of the PR or the thought process that led to it.

          It is, because it means the person posting the PR didn't even bothered to review the changes they are forcing others to review.

          Just clean after yourself before asking others to read your stuff.

    • jhealy 9 hours ago ago

      > No one is ever going back and reading individual commits

      I do, regularly! In a repository where care has been taken, it can be super valuable when tracking down a bug or regression, and understanding the intent of the author

      • bad_username 6 hours ago ago

        The debate between these who don't squash and these who do is the debate between these who use the history for bugfixing and those who don't. And I think not using it is throwing away a super valuable tool that can reduce the fix ETA by an order of magnitude.

    • jolmg 9 hours ago ago

      > No one is ever going back and reading individual commits.

      Straight from the git-log, maybe not, but sometimes you see code that makes you wonder how it came to be and it can help a lot to see it in context of the commit that introduced it. That'd be less helpful if that commit were some huge thing making lots of different changes at once.

      • paxys 9 hours ago ago

        Seeing the individual change in the context of the larger feature is actually more helpful. Otherwise you find a tiny commit that changes A to B and then have to chase down 13 other commits around it to figure out why that change was even made.

        • jolmg 9 hours ago ago

          Yeah, there's a balance. I try to make my commits so they make sense on their own.

          > commits around it to figure out why that change was even made.

          A commit should be such that the message can articulate the why.

    • nextlevelwizard 7 hours ago ago

      How do I know you don’t work in a big team from this?

      First thing I do every time I come back from vacation is to read through our git history to see what has happened.

      It is also very useful when CI breaks. In fact I probably use some form of git history reading every day at work.

      Also if your code base is so tiny and the features you work on are so small that you can just squash everything then maybe that is fine for you. I definitely love being able to actually see what is going on and selectively cherry picking or reverting commits

    • christophilus 41 minutes ago ago

      I’m with you, but it’s obviously a sensitive topic for a lot of folks, based on the replies. Some people’s brains are just wired differently, I guess. I rarely look at history, other than git blame. For me, history does not need to be granular at all. The replies make it sound like curating git history is the job, rather than shipping solutions to customers’ problems. I guess, if it helps you ship faster / better, more power to you.

    • broodbucket 9 hours ago ago

      Having a well curated one-logical-change-per-commit history is incredibly valuable when bisecting a regression.

      • efilife 9 hours ago ago

        Didn't you mean "dissecting"?

        Edit: thanks guys, that's very useful knowledge! Could have saved me many times in the past

        • psadauskas 9 hours ago ago

          Nope, `bisect`: https://git-scm.com/docs/git-bisect

          Figure out a command to test it, a known-good sha and a known-bad sha, and it will binary search its way through the history to find the commit that introduced the failure.

        • seba_dos1 9 hours ago ago

          Check out "man git-bisect".

        • jolmg 9 hours ago ago

            man git-bisect
    • aardvark179 5 hours ago ago

      Having maintained internal forks, and having needed to pull in and rebase upstream changes I do read a lot of commits. Projects that take care with their commits are much easier to work with.

      This is also true when creating with security patches and other things that need to be backported to multiple releases.

    • Hendrikto 3 hours ago ago

      I am always aghast at how proudly people pronounce that they don’t know how to use one of the most central and essential tools in the belt of a software engineer.

      Maintaining history is well worth it, and allows you to use tools like

          git rebase
          git revert
          git bisect
          git blame
          # …
      
      It also makes reviewing and understand your code much easier.
      • fragmede 3 hours ago ago

        git bisect, connected to a script that outputs good/bad, is one of computing's crowning achievements, imo.

    • Izkata 8 hours ago ago

      I do multiple times a week, with repos that have barely been touched in a decade and all the original devs are gone. Squashing would make figuring out why something is the way it is a lot more painful, so I'm glad these repos are svn where squashing wasn't an option. Several times I've discovered bugs that were introduced in linting commits that would have been squashed, so the fix ends up trivial since the intention is already there in the previous commit.

    • CuriouslyC 2 hours ago ago

      Squashing everything has a significant downside compared to functional atomic commits: git-bisect gets WAY less useful.

    • msteffen 8 hours ago ago

      One use-case for curating commits other than git history is carefully structuring code reviews to be easy to review. Eg "commit 1 just rearranges existing code, no business logic changes"..."change 2 modifies business logic, but in one localized place as the refactoring has already been done"..."change 3 only modifies comments"

    • Cthulhu_ 4 hours ago ago

      I have a more nuanced view of this; in libraries and software projects that span years like Linux, curl, etc, this happens all the time. Bugs get fixed and they can point to the exact commit where it was first introduced, and that commit contains all information necessary to figure out why it was introduced in the first time.

      But that's projects like Linux, which is a whole different use case than for example what I do for a living, front-end applications that have at best a lifespan of 10 years and whose individual features / screens / components have less than that, and it's much more rare that an older commit is still relevant today.

      (that said, looking history up has made me dislike squash commits. I get it from a pragmatic point of view but it's not ideal)

    • seba_dos1 9 hours ago ago

      Of course we do and it helps tremendously when the graph is reasonable.

    • smcameron 7 hours ago ago

      Disagree. You need small, git bisectable commits. Use stgit to do it and it's nearly effortless.

    • EPWN3D 9 hours ago ago

      Sorry, no. Just because you've never done it doesn't mean that no one ever will.

      Beyond the archival benefits, I've found plenty of bugs by going back through my "wip" commits and creating a sane history from them.

    • sitkack 8 hours ago ago

      That is like saying once the program is done, throw away the source.

      Lemme guess all your for commit say "wip"

      • yjftsjthsd-h 8 hours ago ago

        It's really not. Source code, even with no history, can be modified, adapted, ported, fixed, and improved. Having history is nice, but it's way lower marginal utility.

    • dkdbejwi383 4 hours ago ago

      I could count the number of times I've written a detailed summary in the body of a commit message, and had it read by my colleague reviewing who then didn't need to leave a comment on the PR asking why I did _x_ on zero hands.

    • Myrmornis 9 hours ago ago

      One good reason is to keep your tests separate from the fixes that make your tests pass. That way you can check your test fails before the next commit makes it pass, eliminating the risk of a false negative (test passes that would have anyway).

      • Cthulhu_ 4 hours ago ago

        That's one approach I suppose, it leaves evidence of "I wrote a test first" and such.

        However, it also feels more like a "work log" than a "commit log"; I like to make my commits atomic (test + code at the same time), so that in theory, each individual commit will pass CI. If you separate them, you can't just revert one commit, you need multiple.

      • assbuttbuttass 9 hours ago ago

        That sounds like it would break bisect

        • bonzini 7 hours ago ago

          You can develop with failing tests and reorder them after the code change before publishing your branch.

        • Myrmornis 9 hours ago ago

          Fair. I think what I'd say is that we don't have to use plain git bisect -- it would be quick to make a bisect script that doesn't land on the failing-test commits. Especially seeing as most teams squash before merging, we should have the freedom to create failing-test commits.

        • jolmg 9 hours ago ago

          Right, maybe a better way to get what they're going for would be

            git checkout @~ ^tests
          
          where ^tests is zsh's way of saying * except for tests. So you get the tests/ of the current commit and the code of the prior.
        • locknitpicker 8 hours ago ago

          > That sounds like it would break bisect

          Nonsense. First off, you can pick the starting commit, and nothing forces you to pick the test one. Second, bisect is designed to tracks changes from good state to bad state based on your personal criteria of what good and bad is. This means that you are free to put up tests that make sense to you (i.e., all tests except the one that was added as a red test) and even not run a test at all.

          • account42 11 minutes ago ago

            And you can also use bisect by first figuring out the broken commit some other way and then marking everything as good if its before that one or bad if its after - but that's not a very productive use of bisect and if its the only available one I think its fair to call it broken.

    • fragmede 7 hours ago ago

      > No one is ever going back and reading individual commits.

      Hell yes we are! Just because you aren't going to doesn't mean nobody else is going to.

    • penguin_booze 6 hours ago ago

      Might as well go back to the tar.gz days, eh?

    • locknitpicker 8 hours ago ago

      > No one is ever going back and reading individual commits.

      Your assumption doesn't match the real world practices I've experienced for years across multiple jobs. Even at the PR stage a clean commit history is of critical importance. Nowadays, with ai coding assistants assuming a central role in developing software, commit history is even used as input with context signal, allowing for flows such as "evaluate the changes in commit X and Y and apply the same pattern to project Z".

      Just because you don't use a tool properly that doesn't mean everyone around you makes the same mistake.

    • vcf 9 hours ago ago

      I almost never went back to read the history, but now I often have Claude go through the history when I wonder how we got to a certain point. It can point me to the relevant issues as well. Squashing is fine, up to a point.

    • LtWorf 6 hours ago ago

      Spoken like a guy who really really doesn't understand how git works and has never bothered to learn!

    • ex1fm3ta 9 hours ago ago

      I do not agree at all. When you have multiple repos accross different services, commits are the best way to follow up with differents changes. We adopted conventional commits guidelines a few months ago and everyone is happy. Even ClaudeCode is able to keep up and auto fix stuffs with the proper commit messages. The changelog is dynamically updated. Everything so smooth when those commits messages are perfectly synchronized.

  • nine_k 11 hours ago ago

    In short, newer versions of git implemented three really frequent use cases of `git rebase --interactive` as separate lower-friction commands. Apparently they only work when there are no conflicts.

    • BobbyTables2 11 hours ago ago

      Wonder if the history command is all that useful.

      I prefer the interactive rebase and use it frequently.

      Would much rather “visually” move commits around than accidentally aim “git history” at an orphaned commit hash no longer in my local branch.

  • whilenot-dev 3 hours ago ago

    Cool, didn't know about `history fixup`! I only ever did the manual dance with `rebase -i` and `rebase` for all other branches. That and `history split` will sure come handy!

    What happens with a conflicting fix though? Do I still need to resolve all conflicts on the base branch and `reset --hard` all other branches?

  • quibono 3 hours ago ago

    > scary rebase -i commands that can leave your tree in a half-broken state if you so much as sneeze

    I'm glad to hear it, I thought that was just me. It gets especially hairy when moving commits around...

    Plus I have 3-way diffs enabled and I usually get confused by which section is which at least once a day.

    Also: does anyone know if `magit` has history support?

  • paularmstrong 10 hours ago ago

    `git history split` is really going to help me help juniors break up their large PRs into smaller more concise changes. If only it had the option to split an entire branch in two easily.

    • jolmg 9 hours ago ago

      Maybe the issue is they think of a PR as an expensive thing. Would be best if they could just do the small thing and make a PR of that from the get-go. If they want to base future changes on the ones they just did, they can just create a new feature branch from right there, and just not create the PR of the second feature until the first is merged, or create it and add a note to the reviewer that it includes the changes of the other PR so they should review that one first. Should they want to add changes to the first feature, they just need to checkout that branch, do the changes, and merge to the second feature branch so they're available there.

      • CuriouslyC an hour ago ago

        Small stacked PRs are a NIGHTMARE unless your org is consistently turning around PRs in low single digit hours, and team members are working on decoupled code so you don't have any stack weaving. You end up in a situation where the engineering director and some tech leads really like tools like Graphite, while the entire team working under them mutters irately under their breath daily.

      • ellefire 5 hours ago ago

        It's expensive when you factor in each PR having to wait for someone to come and review it - it's easier to get your work done in larger PRs when that's the case, although it's a perverse incentive

        • account42 a minute ago ago

          Even with low review turnaround, having each PR get to a defined "goal" makes it clear if the early commits that prepare the co-debase for the goal are going in the right direction. If they were submitted as individual PRs the reviewer can only check that they don't break things but has to trust the submitter that the design is right for what will follow.

    • catlifeonmars 10 hours ago ago

      What does it mean to split a branch in two?

      • rmunn 10 hours ago ago

        Probably to take a series of commits and decide "this one goes on branch A, this one on branch B", e.g. if you intermingled fixing bug A and B in the same branch, you could more easily go through and assign each commit to a new branch.

        The existing workflow for that would be (there are several possible workflows, but this is what I would do):

          git checkout intermingled-branch
          git branch bugfix-A
          git branch bugfix-B
          git checkout bugfix-A
          git rebase -i
          # Edit the file, keep commits that fix bug A, drop commits that fix bug B
          git push origin bugfix-A:bugfix-A
          git checkout bugfix-B
          git rebase -i
          # Edit the file, keep commits that fix bug B, drop commits that fix bug A
          git push origin bugfix-B:bugfix-B
        • LtWorf 3 hours ago ago

          So git cherry-pick?

  • shepmaster 10 hours ago ago

    > That last part goes further than git rebase --update-refs, which only moves refs sitting inside the range you’re actively rebasing. git history instead finds and rewrites every local branch descended from the commit (while also having an option to limit it to only the current branch).

    I'm reading that to mean that when I use `git rebase --update-refs` in this situation, where I've currently checked out `D` and update `B` to `B'`:

      A ──► B ──► C ──► D  
            │              
            └───► E        
    
    I'll end up with this state, where `E` remains untouched?

      A ──► B' ─► C' ─► D'  
      │                   
      └───► B ──► E        
    
    (EDIT: Originally I had `E` point to `B'`, which doesn't make sense)

    If I use `git history fixup`, it would also update `E` and end up with this?

      A ──► B' ─► C' ─► D'  
            │              
            └───► E'        
    
    If that's the case, is there a way to get `git rebase` to have the same behavior? I've got decades of `git rebase` burned into my fingers at this point.
    • jolmg 10 hours ago ago

      > I'll end up with this state, where `E` remains untouched?

      Can't, because a commit's hash takes into account the parent hashes.

      Haven't used --update-refs, but reading it, it should result in your third graph. So,

      > is there a way to get `git rebase` to have the same behavior?

      is already the case.

      • seba_dos1 9 hours ago ago

        It won't result in the third graph on its own as E isn't reachable from D, but it could if you first merged D and E together and then used --update-refs with --rebase-merges. You could then just discard the merged branch and only take care of D' and E' on their own (and since you don't care about the merged branch, you don't have to care about resolving conflicts while preparing it either).

      • shepmaster 10 hours ago ago

        > Haven't used --update-refs, but reading it, it should result in your third graph.

        I don't think it does. I tried locally:

          mkdir test; cd test; git init
          touch a; git add a; git commit -m 'a'
          touch b; git add b; git commit -m 'b'
          touch c; git add c; git commit -m 'c'
          git checkout -b branched-feature HEAD~
          touch d; git add d; git commit -m 'd'
          git checkout main
          echo 'change' > b; git add b; git commit -m 'fix b'
          git rebase -i --root --update-refs
        
        And ended up with this graph (`git log --graph --all`)

          * commit (HEAD -> main)
          |
          |     c
          |
          * commit 
          |
          |     b
          |
          | * commit (branched-feature)
          | |
          | |     d
          | |
          | * commit
          |/  
          |       b
          |
          * commit 
          
                a
        
        Replacing the `git commit -m 'fix b'; git rebase -i --root --update-refs` with `git history fixup HEAD~` produces what I'd like:

          * commit (branched-feature)
          |
          |     d
          |
          | * commit (HEAD -> main)
          |/
          |       c
          |
          * commit
          |
          |     b
          |
          * commit 
          
                a
        • jolmg 10 hours ago ago

          Huh.. That's a shame :(. Maybe what it refers to is if you had a branch on B rather than D, it might update that.

          EDIT: Yeah, this seems to be it. `git branch b` on b, then `git rebase -i --update-ref @~3` from main caused branch ref `b` to move from d86229e to 02fcaf7:

            * 1e354fb (HEAD -> main) fix b
            * 40e6f70 c
            * 02fcaf7 (b) b
            | * f4188e0 (branched-feature) d
            | * d86229e b
            |/  
            * 5fe78fa a
        • Izkata 6 hours ago ago

          > And ended up with this graph (`git log --graph --all`)

          Add --oneline to get the compact version from the other reply.

      • rmunn 10 hours ago ago

        Unless E remained untouched because it was not rewritten, and ended up staying parented on B instead of getting reparented onto B'.

        Which is usually not what you want; most of the time you want E', which is E reparented onto B'. But sometimes you want E to remain untouched and stay parented on the original B. Depends on the situation.

        • jolmg 10 hours ago ago

          Exactly, but the second graph where untouched E is reparented to B' is not something that git would allow.

          • shepmaster 10 hours ago ago

            Ah, good catch. That's more of a graphic issue and not what I was trying to express. Updated the OP.

    • lelandfe 10 hours ago ago
      • shepmaster 10 hours ago ago

        I'm not sure that answers my question. That shows a linear set of branches (my-feature-v3 depends on my-feature-v2 depends on my-feature-v1 depends on main). I'm asking about the case where two or more branches fork from a common ancestor and you want to fix the common ancestor.

    • m463 9 hours ago ago

      off-topic, but that is a very clear readable comment you left with those line-drawing characters.

  • hahahaa 10 hours ago ago

    I like to be like an accountant. No editing history. Create a new "journal entry" (i.e. commit) to fix.

    • seba_dos1 10 hours ago ago

      Commit graph is just a data structure. Sometimes it represents a "history", sometimes other things.

      Personally, I like it when project's repository represents the history of the project rather than the history of random things developers do on their machines, but you do you.

      • hahahaa 10 hours ago ago

        I am thinking of remote. Edits before pushing OK with me (they ate equivalent of recloning and redoing anyway)

        • seba_dos1 9 hours ago ago

          Remotes aren't equal either. Sometimes the remote is my other machine, sometimes it's a fork on a forge used for producing CI artifacts.

          It's a good rule of thumb to consider shared branches to be append-only, but not every remote branch is "shared" and, as with any proper rule of thumb, you can always find exceptions.

          • hahahaa 3 hours ago ago

            Ok I amend to what I think I really mean: don't edit history for anything deployed to prod (or released to public or customers) already.

    • what 10 hours ago ago

      You probably shouldn’t be committing things that are broken…

      • plorkyeran 7 hours ago ago

        You should be committing things that are broken all the time. Git works great as a persistent navigatible undo buffer, and you should commit every time you're in a state that you might want to return to.

      • normie3000 9 hours ago ago

        This is likely saying you shouldn't save a word document that contains spelling mistakes.

      • moezd 10 hours ago ago

        With tools like GitHub Actions and some added constraints, it's not always possible. You literally need a commit to trigger the CI workflow and it starts to trash your branch. Besides, aren't we all familiar with git commit -m "typo"?

      • hahahaa 10 hours ago ago

        Commit yes you absolutely can. Merge to trunk? Probably not, depends on your strategy.

  • eviks 6 hours ago ago

    > Every 3 months, for the last 1.5 years, I try it out for a few days, really trying to make it part of my workflow but eventually I give up and go back to git.1

    That's not really trying, let's assume you need 1 week to change ingrained workflows, so you just waste time every 3 months stopping right before the threshold. Better try once every year, but for a few*4 days...

  • runtime_lens 5 hours ago ago

    git reflog is probably the Git command that has saved me the most stress. At some point you stop worrying about experimenting because you realize it's surprisingly hard to lose work permanently. Git is muuch more forgiving than it first appears.

  • krick 6 hours ago ago

    > scary rebase -i commands that can leave your tree in a half-broken state if you so much as sneeze

    Complete bullshit. Might as well say "scary screwdriver that can turn up in your recturm if you so much as sneeze". Sure, I believe that might have happened to you (heard stories from friends that work in the emergency room), but I run rebase -i 10 times during the time I work on each branch (literally: I don't even care to write "proper" commit messages while writing the code, will reorganize and clean them up later anyway), and it never happened to me.

    • eviks 6 hours ago ago

      > commit messages while writing the code, will reorganize and clean them up later anyway

      That's just too primitive of a workflow, so repeating it will not run into the risk. You need to add an actual conflict in some feature branch and get stuck being forced to resolve it to compete the rebase to appreciate the op warning

  • bentt 10 hours ago ago

    Granted, I have a perspective of a game dev, but this kind of repo defiling just gives me the willies. IMO instead of finding a common ancestor and altering it, just make the desired change upstream and merge it to where it’s needed. If you can’t do that then you have already made a deal with the devil and might reconsider your approach. KISS

  • anuramat 3 hours ago ago

    is there a way to use it with lazygit? unfortunately I'm addicted atp, and "autorebase branches" is exactly what I was missing the entire time

  • froh 7 hours ago ago

    TIL, thx :-)

    somewhat related Q:

    how do you give two files the same ancestor? so git log will for each show the history to the beginnings of the originally unsplit file? useful for splitting large files.

    • bonzini 7 hours ago ago

      That's not possible, because files don't have ancestors in git. Each commit's tree is tracked independently and copy/move is just something that's detected via heuristics.

  • _nivlac_ 9 hours ago ago

    I like `git history reword`, would've found that useful in the past (e.g. fixing a bad typo in an older commit).

    It sounds like there was probably an equivalent using an existing command but this is easier for me to understand. Thanks for sharing!

  • SCUSKU 5 hours ago ago

    These graphics are great. Makes for a skimmable high signal article, nice work!

  • rushil_b_patel 6 hours ago ago

    the "reword" option is same as git rebase -i HEAD~n, and then instead of pick replace it with reword to change the commit messsage.

    BTW I have made a notion doc on git commands: https://rushilpatel.notion.site/git

  • Sharlin 4 hours ago ago

    Huh, TIL about `git commit —fixup`.

    • Cthulhu_ 3 hours ago ago

      Yeah I learned that one a few months ago, before that I'd use interactive rebase and shuffle the commits around manually in the editor that opens.

      I appreciate that these commands are just utilities / conveniences on top of a stable base though.

  • smcameron 8 hours ago ago

    > Working with lots of changes in parallel on git can be painful. You end up juggling branches and commits, and running scary rebase -i commands that can leave your tree in a half-broken state if you so much as sneeze.

    I mean, just use stgit[1] to maintain a stack of patches instead of parallel branches, it's so much better. You can easily wrangle thousands of patches (aka commits) with stgit.

    A lot of people, on first encountering stgit, read a bit about it, think "why do I need this? I can do the same thing with just plain ol' git.". Yeah, you can. But not at scale. Not practically. Not with thousands of commits. And it makes the case when you just have a few tens of commits absolutely trivial. Try it for awhile and you'll find it indispensible.

    [1] https://stacked-git.github.io/

  • kazinator 6 hours ago ago

    The thing is, when you are rewriting history to change an old commit, you have to solve the little problem that git commit messages refer to hashes such as:

       This regression was caused in <hash> on December 19, 2017.
    
    The fixup and rewrite of history has to ferret out these has references and fix them to the new hash of the same commit.

    I have scripted this before!

  • skydhash 11 hours ago ago

    > Working with lots of changes in parallel on git can be painful. You end up juggling branches and commits, and running scary rebase -i commands that can leave your tree in a half-broken state if you so much as sneeze.

    I think that only happens when you work on code as text files (i.e character streams) instead of code (i.e structured content with meaning). Like you have commit A and commit B that is in conflict, you should be glad because that's a rough signal that the intent of A and B differs. Your goal should be to think about how to compose A and B so that both intent survives (unless one supersedes the other). Which means you should be at least familiar with A and B.

    The issue I found with people that fears conflict is that they often don't understand either A or B (or both). So they are a bad candidate to actually do the operation. It's not a matter of git's cli interface, it's a matter of codebase comprehension and how well you're familiar with the changes in question.

    • thfuran 10 hours ago ago

      Git is the one treating code like a text file instead of code.

      • UnfitFootprint 10 hours ago ago

        I pull out difftastic when it’s all too hard for this. Diffs based off tree sitter

      • skydhash 10 hours ago ago

        Git store whole files. The diff and the merge algorithm works by line by default, but that's because line is a rough unit of code (statement, expression, and definition happens mostly within one line).

    • bulatb 10 hours ago ago

      I can fully understand a conflict, know it's coming, and fear it anyway because I'll have to deal with Git's behavior to fix it.

      • seba_dos1 10 hours ago ago

        Such as?

        When you merge a commit in that changed a file that has been already changed since the common ancestor, Git runs a tool of your choice on this file. If the tool fails, it marks the file as needing a merge and doesn't let you commit it until you unmark it to confirm that you have merged it manually. In case of octopus merges, it will just abort early. That's basically its whole behavior when it comes to conflicts.

        • bulatb 10 hours ago ago

          Such as moving down a fixup during interactive rebase when it's going to conflict with parents, or I've added more commits mid-rebase, or the rebase started in a tool and now I need to think about the tool's command and understand how many times the rebase point is view is backwards to interpret which is "ours" and which is "theirs" and whether it's the tool, my editor, or my own experience I should ignore because it's going to mislead me.

          None of that word salad should matter, but it does. Git will ruin everything with glee and there is always an excuse for why that's fine and it's the user's fault.

          • seba_dos1 10 hours ago ago

            There's nothing "backwards" in "rebase point of view". It's just automated cherry-picking - it's like applying patches, it's as forwards as it gets. People who think it's "backwards" usually just have holes in their mental model of the repository. And yes, I find tools doing what you're asking them to do to be rather fine. In fact, Git makes it easy to notice when you're adding commits mid-rebase, which is something I often do intentionally, as it tells you what the HEAD is (and even shows a detailed state of the in-progress rebase) while authoring the commit message.

            • bulatb 9 hours ago ago

              I understand how rebase works and use it many times a day. Thanks for trying to explain but I won't respond further.

              • seba_dos1 9 hours ago ago

                These aren't troubles of someone who understands. If anyone else reading this has these kinds of troubles too - don't worry, understanding abstractions takes time and effort, you'll get there eventually (not if you'll keep blaming others though).

                • bulatb 9 hours ago ago

                  Let me eat the crow of getting drawn back in and cap this conversation with a summary. I think this is important because criticizing Git's UX is always like this.

                  OP: No one should be worried about using Git to do a thing.

                  bulatb: I'm worried it will be unpleasant.

                  seba_dos1: Here is what will happen when you do the thing.

                  bulatb: I know, but doing it will be unpleasant.

                  seba_dos1: You must not understand what's going to happen.

                  bulatb: I do. The process is unpleasant.

                  seba_dos1: You must not understand what's going to happen.

                  • seba_dos1 8 hours ago ago

                    Had you actually read what I wrote, you would rather summarize it as "Git is showing exactly what's going to happen when you attempt to do it, all you have to do to make is pleasant is to not ignore it". Reading things requires unpleasant effort though, I get it.

                    • bulatb 8 hours ago ago

                      I'm sorry (like actually sorry) if I'm getting into counter-condescension here, but, like...

                      > all you have to do to make is pleasant

                      This is an assumption about what I find unpleasant and why. I take it you think "reading information" and "understanding instructions" are some of those things I don't like. Your conclusion that I must not understand is based on that assumption.

                      The assumption is wrong.

                      If you can grant me that, my problem looks different. If you can't or won't, my summary was right.

                      • seba_dos1 7 hours ago ago

                        If the assumption was wrong, then your first comment was pretty much useless, and the second one didn't help either as it just describes doing things carelessly and without proper understanding. So if that reading of it is wrong, then it was just complaining for complaining's sake and not about Git at all, but rather about what you happen to find scary for some undisclosed reason?

                        People do have genuine troubles with these behaviors when they don't grasp what's going on well enough. These troubles go away pretty much entirely once they do. I think explaining them is the only thing one could write in such thread that will be useful to anyone, as the Git's UX already does make a pretty good effort to help the user orient themselves in these cases and has been visibly improving in this regard over time.

                        • bulatb 2 hours ago ago

                          My point to the OP is the same thing I'm saying to you. "I understand the thing and think it's fine" does not imply that nobody who understands the thing can think it isn't fine, or anyone who doesn't like the thing just doesn't understand it.

                          It's not some deep or interesting idea, but it needs to be repeated any time "git gud" is used as an excuse for Git's UX, which is always.

          • skydhash 10 hours ago ago

            > which is "ours" and which is "theirs"

            "ours" is always HEAD, usually meaning the state of the working_tree, "theirs" is always the commit that is going to change the working_tree.

            When merging, you are taking change from another branch (theirs) to create a new commit on the current branch (ours) that ties the two together. When rebasing interactively, you switch to the new base (ours) and replay the changes of the branch (theirs) according to the edit file.

            Etymology matters. The conceptual model of git is simple, but people only focus on the operations. That's like trying to learn algorithm and data structures and focusing on the words "insert", "remove", "find", without trying to learn "list", "stack", "tree",... first.

            Instead learn about Git's glossary [0], then how the operations use and modify those concepts.

            [0] https://git-scm.com/docs/gitglossary

  • xyzsparetimexyz 5 hours ago ago

    Tldr; use jj