Hacker News new | past | comments | ask | show | jobs | submit login
Rewrite Git history via drag-and-drop (retcon.app)
86 points by surprisetalk 4 months ago | hide | past | favorite | 104 comments



I want to be able to split a single commit into multiple commits. I sometimes mix clean-up changes with core logic changes in a single commit. That is something I'd pay for. To be able to just drag'n'drop the files from commit to commit. Especially if I could split changes within a file between commits. Something more powerful than the partial commits of Intellij.


Lazygit patches are a great way to do this. You can interactively select lines from commits to “pull out” making them easy to form new commits with. Takes some getting used to, but it is the exact flow you are talking about.

https://github.com/jesseduffield/lazygit?tab=readme-ov-file#...

Oh you edited to say drag and drop. Lazygit is a TUI and patches are very much keyboard driven. Still worth thinking about? It’s free!


You may find Jujutsu appealing. Particularly the jj split subcommand.

https://martinvonz.github.io/jj/latest/cli-reference/#jj-spl...


I'm actually working on adding this to Retcon right now! It's one of the biggest feature requests.

So far the implementation goes like this: you enter Edit mode on a commit; you unstage some lines; and you confirm. The lines are yanked from the commit, and added to a new commit that you just have to title. I just use it on the Retcon repo and it's real cool to have.


You can do this, via the command line at least, using `git rebase`:

https://stackoverflow.com/a/6217314


The way I do this, I duplicate each entry for the commit-under-splitting N+1 times when splitting it into N parts. Then for each, I manually edit the commit to its desired state during the interactive rebase, and then the last one should be empty (or only consist of leftover changes that should be dropped).


(Assuming you haven't already pushed to remote)

Create a new branch, called "preSplit", at the commit where you want to split. Take your actual branch and reset it to one commit prior. Grab the first set of changes you want from "preSplit" and commit. Repeat until each distinct set of changes has its own commit. If needed, rebase commits after "preSplit" onto your current branch.

I'll do it for you, for a modest fee!


I do this constantly via the command-line in 5s. git fp, patch, git rebase


Very slick! But tbh this isn't the difficult part, conflicts are. I suspect not many people will pay for a GUI interface to `git rebase -i`.

If you can make merge conflicts less dumb then I'm there!


I'm just going to drop a casual shout-out to jujutsu[1]. It elegantly solves things like rebase/merge conflicts (and solves a lot of other sharp edges in git at the same time). It eliminates the need for WIP commits, stashing, and a host of other workflow bandaids we’ve all internalized. Best of all, it’s 100% git-compatible, so you can mix and match jj and git commands whenever needed, your coworkers never need know you're using something else, and even if it never gain critical mass you can still just use it and have superpowers while everyone else lives in the metaphorical stone age.

It is one of those rare birds that is both more powerful than the tool that it replaces while also being drastically easier to use. I am (was?) a git power user. It took me all of a day to replace git with jj and generously the rest of the week to become essentially as fluent. I will never go back.

Chris Krycho's post[2] was what originally sold me and I hope it sells you too.

[1] https://github.com/martinvonz/jj

[2] https://v5.chriskrycho.com/essays/jj-init/


I'll add that while `jj` itself is a CLI, people have made GUIs on top of it that allow for drag and dropping of commits:

https://github.com/gulbanana/gg https://www.visualjj.com/


Came to plug jj as well.

Steve klabnik's tutorial is excellent as well. https://steveklabnik.github.io/jujutsu-tutorial/introduction...


Yeah I've heard of it. I was put of by the removal of the staging area which I think is one of Git's nicest features.

Maybe I'll check it out. Deferring conflict resolution is definitely a killer feature.


This was the exact thing that kept me from trying it sooner. I wish I’d realized that that doesn’t imply an “everything gets committed” approach.

It’s trivial to split a change in two. So your working copy is constantly snapshotted, and when you’re finished you `jj split` and choose the parts you want to keep. The rest is moved out into a new change.

That workflow is in practice basically identical to the `git add -p` one, though the terminology is a bit different and there are some greatly simplifying changes under the hood.


FWIW the concept of undo/redo is at least novel. Agree it’s not worth paying for though, lazygit does all of this (even undo/redo) for free, as well as… the rest of git workflow.


(Retcon dev here)

lazygit is really cool, and is a lot more full-featured than Retcon. But, the core "rewrite with zero friction" feature of Retcon is still unmatched, I think.

For instance: while lazygit does allow you to reorder commits without entering a separate mode, that's only if each move is conflict free. If you have two commits that need to both be moved at once, then in lazygit, you'll have to resort to a regular interactive rebase (so, with the separate planning and execution steps, no undo or preview along the way, etc).

In Retcon, if a commit move results in a conflict, that doesn't matter; you can keep making changes to your history anyway, and then resolve any remaining conflicts when you're ready. It makes the workflow super fluid.

There's probably still a ton Retcon could learn from lazygit/magit/jj, though!


> In Retcon, if a commit move results in a conflict, that doesn't matter; you can keep making changes to your history anyway, and then resolve any remaining conflicts when you're ready.

I didn't realize Retcon could do this from the website, nice!

I wonder how similar your approach is to [jj's approach to conflicts]; whether you reinvented the same way of modelling conflicts in the repo or use a different one. (See also the link to the technical docs from that page)

https://gitbutler.com/ also [borrowed this idea] from jj.

[jj's approach to conflicts]: https://martinvonz.github.io/jj/latest/conflicts/

[borrowed this idea]: https://blog.gitbutler.com/fearless-rebasing/

So, there are several tools exploring these ideas, but there are interesting differences in (for example) how close to Git each of these approaches stays.


Thanks for the link; jj's approach seems really solid.

Retcon is pretty different: during a rebase, the state of everything is only stored in RAM, not serialized to the repo. So while you can postpone resolving conflicts until you're done putting commits in place, you do have to do so before you go do something else in your repo.

The RAM representation is basically a list of commits (well, commit-likes), what I call a virtual history. It's the history you want to get to, but that's not currently representable with a regular, physical Git history.


> many people will pay for a GUI interface

Then many people should purchase SmartGit client. Which supports more of the same thing (with couple more clicks, granted) but also has a proper tree view. Also supports linux ffs.

Never working with git without it again.


Looking at the docs I'm not sure what functionality that adds over git. It seems like just a GUI, no extra abstractions for the complicated operations. E.g. modifying older commits[1] still looks to require manually branching, resetting, making the modification, rebasing/cherry-picking from the previous branch, fixing any conflicts, and then deleting the previous branch. That's pretty shitty for a wrapper, it should just be "right click the commit, click modify, make edits, resolve any conflicts". The porcelain shouldn't expose the plumbing so much!

[1] https://docs.syntevo.com/SmartGit/Latest/HowTos/Modifying-th...


> "right click the commit, click modify, make edits, resolve any conflicts"

I don't know why the docs are this way, it's literally that. Maybe old version or something. This page is closer to the truth.

https://docs.syntevo.com/SmartGit/Latest/Manual/GUI/Branch/R...

You can download it and check it out, they have trial licenses.


I’m happy with Jetbrains conflict resolution, but the I’ve never tried SmartGit for comparison.

It would take a lot for me to move because I already pay for Jetbrains IDE.


I don’t think SmartGit will elevate you that much but JetBrains IDEs and SmartGit are the only two tools I pay for and have for 8 years with no regrets.

I already posted in this thread but I just love these two tools and wish more people knew about both of them.


+1 for SmartGit. It's much more intuitive and flexible than the JetBrains UI, which still inherits so much terminology and behavior from its "unified" view that includes being able to handle Perforce changelists. It's a bit of a mess and generally trips new users up more than it helps. If you're comfortable with it, then good for you but I've had a lot of students not being able to grok it really well.


I used to feel that way about JetBrains, but I don’t notice those abstractions anymore. IDK how much of it is the iterative changes they have made over the years vs me getting used to it.


OK, I don't get it. There's lots of praise for this though so I must be missing something that lots of other people get value from, so perhaps someone could be kind enough to explain where's the benefit to this?

I'm fine with the history capturing what has actually happened. a Git history isn't something that is supposed to be admired as if it were a work of art.

The git history is the scaffolding, not the cathedral itself.

Even the source code isn't the cathedral, that's more super-structure. The product is the goal.


I have worked with people have justified downright trash with "it's not supposed to be a work of art".

That way lies madness.

Code that takes a minute to write takes ten minutes to understand. Code is first and foremost for humans to understand, before it is for machines to execute. Otherwise there would be no need for comments, or sane names for functions. Or commit messages. Please be considerate to your readers.


I think it is a good practice to clean up your branch before you merge it into master.

So instead of:

   * Change 1
   * Fix typo
   * Change 2
   * Another typo
   * Change 3
   * That didn't work
   * Ops, I did it again
   * Revert Change 3
   * Change 3 (final)
You'll merge:

   * Change 1
   * Change 2
   * Change 3
Which is much better, particularly if you have hundreds of developers working on the same codebase.

And it is very easy to do that using `git rebase -i`.

(I don't see the need for a GUI)


Okay, I guess this is also a consequence of having long lived branches that multiple people contribute to versus short-lived continuous integration into main.

I can also see value there if you're not squashing commits at the PR level. I prefer just squashing commits so main becomes:

  - Feature 1

  - Feature 2

  - BugFix 1

  - Feature 4

etc.

The individual branches have the "dirty" history which can be useful, and main is kept neat by having feature of fix-level changes which are quality controlled through gated-commits.

If you had to work on long-running feature branches which were more of a free-for-all so /branches/feature effectively becomes your "main" then I could see much more of an argument for re-writing history of individual contributors before merging into that feature branch.

I'd still argue you should just set up proper quality control on the feature branch and squash commits going into that, but that's the kind of overhead that can frustrate some teams, so I can better understand now the desire for a half-way cleaning between squashing and the full dirty history.


I'd rather have the dirty history than the clean one. It seems really useful to have a record of an approach that didn't work, to save others from trying it again.

To see a "clean" history, I can always use log options like git's -first-parent. It works great and doesn't delete history.


I don't get your point. Sure, the git log isnt the "cathedral", but also being able to change things quickly doesn't imply or necessitate this.


My point is that I don't understand where the driving force for desiring to change it at all is coming from.


Git blame and bisect do care about the state of specific commits.

During development of a thing it should be desirable to be able to handle/test just whatever the current thing is and clean up afterwards if necessary, without having to completely drop ability to use git. But this can impact later bisects - having temporary printf("fuck sadjkoisajhdfo")s spamming outputs, project entirely not building on a configuration that wasn't cared about at the moment (or worse, build successfully, but function off enough that it's not obvious that the commit was not intended to be touched).

And then there's the general thing of having a feature that you had been working on, but want to move it to some other branch. Or you committed things out of order and the committed order doesn't actually build in the middle. Or you didn't commit some file/change and thus have a sequence of ten completely-non-sensical non-functional commits.

The inverse question deserves asking - why would you want to leave in your primary commit history things not meant to ever be looked at?


Is there no way to pay once and keep forever? Also, will it be available through homebrew?

Why is everything turning into subscription based? I understand that it is more favorable for the creator but I can't imagine having to pay monthly for everything I use. Imagine one day when my economy gets strangled, do I loose everything I can't afford subscribe to anymore?


Totally understand the dislike for subscriptions. I did go that way because it makes it much likelier I'll be able to work on the app long-term (which I'd really like!).

Retcon's actually already available on Homebrew—someone kindly added it, unprompted!


I understand your reasoning


design flaws as a feature: I like that rewriting git history is hard. immutable history is a good thing from an auditing perspective when you are in a centralized flow


There's no reason it needs to be hard in my branch before it gets merged, though.

And with the way Git stores information, sometimes you don't have any option but to rewrite history. e.g. when something changes on a committer identity, you have to rewrite all of their commits since that information is denormalized.


Now that's interesting. Are you talking about the commit author data, or something else?

FWIW, this sounds like the kind of thing that signed commits would solve. If the coder/user commits anything that isn't signed, they can't push it into the origin repo in the first place.


Yes, commit author data is what I was referring to. Both name and email address changes sometimes need to be retroactive, especially in corporate environments using GitHub or Azure DevOps.


yeah but theres no reason you have to do it that way. Just make your own local branch and squash merge it into a singular commit when ready


Hopefully this is mostly intended to rewrite/polish local history, before it’s pushed upstream.


This looks like a nice tool, but I agree with GP because as a reviewer I don't care about a "clean" commit history in a branch I'm reviewing. I care about what's changed, and imo the request description/annotations can describe that in plain language better than a commit history can tell a story.


You need to look further ahead than that though. A sane git history makes debugging much easier. When you bisect your way to a problem area, sure is nice when the suspect lines of code fall into a 10 line change commit with a nice message and body providing context. I’ll let it slide if the PR/MR has a lot of good context, because it’s trivial to link those back to commits/lines.


I also think we should be thinking more long-term. How understandable is the history when you're trying to figure out why something changed? I usually try to tell the story of what changes are being made rather than treating every clump of commits as a "PR" that's just going to be squashed together anyway. I think a lot of valuable information is lost by doing that. But I realize that that train has left the station for most, so I'll just shut up now.


I've always seen the clean commit stuff as a "I'm a junior and need to figure out how to logicaly lay out my thoughts" and push people away from uni commit model. clean commit purists take it a bit too far


It'd be nice if there were a GUI way to rebase by dragging links in a graphical view of the DAG. This program seems to allow reordering commits, but it's not clear how well it handles the more complex cases.


If I am not mistaken Git Kraken has a limited version of that.


Having used it, no, it doesn't. At least not that I could find. Last tried it about a year ago though, so they might have added it. IIRC it was just pretty graphics over exposed `git` workflows, instead of any higher-level abstractions.


See the animation https://www.gitkraken.com/learn/git/git-rebase#how-to-git-re... . It is very limited as I said (happens at the branch level not individual commits and you can't choose base), but at least it solves one of the most annoying (but solvable) parts for me - remembering which of the 3 arguments for "git rebase" is which and in what order they go. Even in GUI clients where you have single "rebase" button interacting with current branch it's not always fully obvious whether it will rebase current branch or on top of current branch.

Of course it's not hard to imagine how a program could potentially do a lot more. And I would understand if compared to that you called the functionality GitKraken provides as having nothing at all.


Here's a recent informing podcast episode about Retcon with its author, https://www.devtools.fm/episode/116


QUESTION: How does this handle merge conflict when rewriting the history??


If there's a conflict, Retcon shows that to you, but you can keep freely moving commits around—it's not blocking. Once you're happy with how your history looks like, you can start actually resolving any remaining conflicts, and after that the history gets actually written.

Sometimes, just moving things around further is enough to resolve the conflicts, too, if they're simple enough!


Cool, but I'm not going to pay with a subscription lol. This is a tool I'd pay 20$ for, at most. (once, absolutely not monthly or yearly) and only without any of the "up to X devices" shenanigans.


I was contemplating writing something similar, but am often hesitant to post negative comments, but the pricing (without even considering the user and seat restrictions) of this is just crazy considering it's ultimately a GUI wrapper of the CLI tool.


Agreed. I’d pay for this (I pay for [Fork][1]), but never as a subscription.

[1]: https://git-fork.com


Yeah, I don't get who's going to be paying $10 a month for a nicer `git rebase -i`


Why not git-butler, I find that tool very useful for this task!


To save people a search: https://gitbutler.com/


FYI smartgit does that. Also in IntelliJ's git ui, the rebase option allows drag drop of commits.


IntelliJ and SmartGit are my two favorite tools.

SmartGit has had drag and drop for a long time. I actually rarely use it but there is almost no Git problem I can’t fix in like 2 clicks.


Moreover, both let you select and skip individual lines/chunks from a commit. As in when selecting files to commit, you can choose which changed lines you want in that commit.


I would rather have a messy commit history with all of the value that an audit trail brings va a clean history that purges said context.


Here ya go:

   commit   f5b5bd8f9eaa443d4020cbe918x742e7ddd22000
   Author : John Doe <John.Doe@mail.com>
   Date: Mon May 22 14:21:03 2023 -0400.
   
   merge main

   commit   f5b5bd8f9eaa443d4020cbe918x742e7ddd22000
   Author : John Doe <John.Doe@mail.com>
   Date: Mon May 22 14:21:03 2023 -0400.

   fml

   commit   f5b5bd8f9eaa443d4020cbe918x742e7ddd22000
   Author : John Doe <John.Doe@mail.com>
   Date: Mon May 22 14:21:03 2023 -0400.

   fix 2

   commit   f5b5bd8f9eaa443d4020cbe918x742e7ddd22000
   Author : John Doe <John.Doe@mail.com>
   Date: Mon May 22 14:21:03 2023 -0400.

   fix 1

   commit   f5b5bd8f9eaa443d4020cbe918x742e7ddd22000
   Author : John Doe <John.Doe@mail.com>
   Date: Mon May 22 14:21:03 2023 -0400.

   CI fix

   commit   f5b5bd8f9eaa443d4020cbe918x742e7ddd22000
   Author : John Doe <John.Doe@mail.com>
   Date: Mon May 22 14:21:03 2023 -0400.

   PR comments

   commit   f5b5bd8f9eaa443d4020cbe918x742e7ddd22000
   Author : John Doe <John.Doe@mail.com>
   Date: Mon May 22 14:21:03 2023 -0400.

   Linter

   commit   f5b5bd8f9eaa443d4020cbe918x742e7ddd22000
   Author : John Doe <John.Doe@mail.com>
   Date: Mon May 22 14:21:03 2023 -0400.

   Fix test

   commit   f5b5bd8f9eaa443d4020cbe918x742e7ddd22000
   Author : John Doe <John.Doe@mail.com>
   Date: Mon May 22 14:21:03 2023 -0400.

   Implement new SSO feature


Is the reuse of the commit hash and date intentional and part of the joke?

Besides that, I like seeing and preserving this kind of history. And when I don't want to, there are ways to filter the logs.


How is a "PR comments" commit useful to you? If I'm looking at history, it's usually to see: 1. What caused a bug 2. Context around a feature and why it was written a certain way

Seeing a "PR comments" commit just turns into noise. It also makes me gather 10 commits together to try to piece back together the unit of work that was built. I just see no value in preserving this type of noise.


That is a perfect example. The "PR comments" commit helps me see what the dev considered most important (code before this commit), and what the rest of the team considered lacking (the content of this commit). Thus, the Git history records a facet of the team culture at the time of the commit.


No, you're making up that story and that culture, and when you lose this spurious foundation, you'll just as easily make up some other story based on any other random data.

For example, reality could've been that there was no team involved at all and all those changes came to the original person the moment he made the PR. And the "PR comments" could just as easily refer to his own comments he added during when checking those CI messages and noticing something else and commenting on that not to forget.


In my experience the merge commit is simply a reference to the PR, which has all the context. The title of the PR is effectively the commit summary.


For most things (or, well, that depends on what one commits I guess), the filtered form will likely be the more preferable one. If you want to keep around some of the largely-useless stuff just in case, you can `git tag backup/sso-garbage` or similar before rebasing.

For fun, here's a git log pre-rebase of some backup tag I have (final commits: https://github.com/dzaima/CBQN/commits/eccbac37ab15bd68320d9...):

    f6bc866f (tag: backup/pre-rebase-si-bitwiden) ..aarch64
    0fd19c39 Singeli n→8 bitwiden
    ed2a0655 more Singeli utils
    556aa17b use q_fbit more
    a28adcbb minor src/README.md cleanup
    d6d40fc7 .warning comment
    9dcf2f75 .don't need customizeShape for explicitly-created bitarr
    958a04a1 update Singeli submodule
    159ee16e ..
    ea43cb2d .
    b067d7a8 !!
    c588a381 fix ⟨1‿2⟩⊸⊏˘ mat
    0e251720 .
    8f049ede fast inds⊸⊏˘bits for 4-bit & 2-bit input & output cells
    def8c196 fast inds⊸⊏˘bits for 8-bit input & output cells
    1638f8d4 .valgrind false-positive hiding
    1023aaa5 --replxx-read-only
    bee4169e .more valgrind improvement
    c3643fc6 use custom valgrind pdep/pext everywhere
    45796542 fix out-of-bounds load on empty replxx line
    bc5894b9 make bitp_get & bitp_set load/store u8 instead of u64
    3b4381b2 include last power of two in fast-path ⌽˘
Most of that didn't compile on aarch64 before that last commit, even changes that could affect aarch64 as I sprinkled in some other things while working on the "main" thing as they came up.


I take a similar approach where I have branches named `my_feature/x` where I start with `my_feature/1`, do some stuff and make a messy commit history, then when I feel like I want to clean up the commit history I branch of that to `my_feature/2` where I rebase/squash/reorder/rewrite away and continue from there. That way if I lose something important I just go back to an earlier branch. for complex features I can easily get to 15 of these branches. And I just delete them when I'm done.

I find this works really nicely, I can periodically clean up my commit history and do a full review of my changes so far and make sure they're all coherent before continuing. And doing this regularly makes it much easier to keep the commits nicely self contained. It's like `final_version_final_ii_for_real_final.xlsx` on top of git


Yes, this is great! It's like I can see you coding, your process is captured in history.

When I just want the end result, I can filter the logs or look at the merge commit. But this is valuable too - especially since you yourself might look back at it and remember not just what you wrote, but how.


Filtering requires a filter to exist, which is time alternatively spent doing rebasing (esp. awful if you're not the one who wrote it and now have to make sense of the awful mess to achieve literally anything out of it). And that log contains like 4 completely independent things, which wouldn't ever make sense in a single merge anyway (unless you like awful merges of a bunch of random things thrown together in a random order, at which point reading the merge commit message now also requires scanning through and ignoring a bunch of unrelated things, and tracking which change corresponds to which commit named "."; never mind that a merge commit necessarily cannot relate notes to code changes as good as commits can; never mind that this requires a merge commit to exist in the first place, which too is time that can alternatively be spent doing nice rebasing).

As fun as it might look, I'm fairly certain that the original commit contents are entirely useless to anyone who isn't me, and by this point they're pointless to me too. I'm fairly certain it's entirely pointless other than a trip down the memory lane (which, granted, can be quite fun, but is entirely not worth basing the primary git log around).


No I was just lazy.


So? Even without good commit messages `git blame` will tell us who touched what and when.


Not necessarily; if one commit touches all lines (or a bunch), and another reverts that, the blame is thrashed; much worse than having rebased the temp change away. And a commit name of "." is quite significantly less useful in a git blame than "Rewrite foo to use new thing" when looking at reasons for why foo might have broken.


Great idea, one more step towards Copy&Paste to achieve the same. Treat commits as files in a file manager from the UI perspective


Is there a GitFS exposing Git commit history as a FUSE file system?


You're in luck! git history is already built on top of as filesystem


Technically correct :p But I’d be pretty scared to go and change the contents of .git by hand ;)


This seems similar to Sublime Merge. It’ll be interesting to hear a comparison from someone who’s used both.


I use Merge, but i don't use it for anything more than trivial rebasing. I'll split commits in merge then just go run `git rebase -i`.

What i want is for something to have a plan-THEN-act approach to rebasing. Like GParted, or... `git rebase -i`.


Thanks for the pointer - Retcon sounds useful but I don't have a Mac. I'll have to give Sublime Merge a try the next time I need to do some rewriting...


I use sublime-merge as a daily driver. AFAIK, it doesn't have a comparable feature for re-ordering commits.


I've been using Sublime Merge for exactly this purpose since around when it was first launched.


Clean landing page -> clean product. What's the meaning behind the name 'retcon'?



Thanks! learned something new today


Do people end up rewriting git history often? I think I had to do a handful of times only, so it is really hard to merit a tool that requires an annual subscription to do this.

Additionally, Sublime Merge seems to have significantly more features with fairly similar UI.


Just curious what you used to generate the video? I like the per pill progress bars.


Thank you!

It's a regular video recording, and then I noted down the chapter timestamps in an array. (see heroVideoChapterStartTimesSeconds at the very top of https://retcon.app/main.js) As the video is playing, the player uses this to know what chapter to highlight, and how much to fill its progress bar. (that's updateVideoChapters())


The UX looks quite decent, but I think it should also have an indicator next to each commit to show whether it was already pushed or not so you can avoid doing a force push.


In what scenarios would you want to re-order commits?


Sometimes, before you merge your changes into master, you may want to re-organize your commits in logical chunks.

For example, if you are working in two different files -- you can reorder the commits so they appear together, and then combine them if that makes sense.


Reading "rewrite history" sets off so many red flags for me I struggle to take this seriously.

What are you trying to do? Are you embarrassed that you arrived at an end goal via a suboptimal sequence of steps, and are trying to present it in a way that conceals that fact? Is the auditor at the door? What's the end goal here?


Rewriting history on main is bad. Rewriting history everywhere else is completely normal and should be encouraged. I don't want your "oops typo LOL" commits in main. I don't want a history that looks like "refactor stuff"->"new feature"->"1 line change to that thing I refactored". That one line change should go into the old commit. Fix all of that before you merge to main.


They’re just talking about interactive rebase, why is that a red flag? At least I work this way, where I make “not so good” commits sometimes, when I know I don’t have a good atomic commit, but want to create a checkin because “something works now”. Then I later use interactive rebase to make the actual atomic commits, with appropriate messages and bodies. Am I was supposed to be perfect on the first pass?


There are a handful of git features which work significantly better with a clean history on main. If `git blame` points at a well crafted commit, it can help bring additional context to the line in question. In addition `git log -S<string>` can be used to find when code was introduced.

Both of these features aren't very useful when they point at a "wip" or similar commit message.

By all means push lots of little commits to your branch while you're figuring stuff out, but squash and rewrite history into logical commits (usually just one) before landing the change on main.


I learned about the --first-parent flag of git blame recently. It allows git blame to work well in repos that use merge commits.


There is also -r, which leaves merge commits and lets you move them around.


Maintaining forks/extensions of opensource upstream projects is a pretty good use for it.


Interesting, could you elaborate? I'm unfamiliar with that usecase


I've maintained an internal fork of "hostapd" tool. We needed a bunch of additional WiFi features and in some places different behavior due to hardware architecture. Initially it had a normal Git history, which made it a pain to update (as a consequence, this was not done at all except for cherry picking security fixes). Merging any significant upstream changes was impossible and all clients would be limited to using our exact hostapd codebase.

The solution was to identify our changes, split them into meaningful feature commits, keeping upstream and our code as separate as possible. After this change, updating the upstream by ~2 years took about 4 days. Most importantly, the history is kept clean by marking what commits go where, and doing cleanup every couple of months (no code diffs are allowed at that moment, only git history may be rewritten).

The new history can also be exported as patches, so that any client can (selectively) apply them on top of their own hostapd.


There's nothing I love more than git blaming and searching through 100s of "oops" and "edit" commits /s




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: