Preferences

> Discussion regarding a commit (is: review) and acknowledgment of a commit cannot happen before the commit has been made.

It can't happen before the commit on a feature branch, but it can happen before merging the commit back to the main development branch. Given that a rebase or merge commit is already frequently necessary to integrate changes from a feature branch after review is finished, I don't see why this type of info couldn't be added (or even required to exist) before merging.


The history-destroying problems of rebasing are a rant on their own.
Zambyte
That's a UI problem with git making it hard to find hidden commits (pre-rebase). The commits aren't destroyed, they are hidden. The Jujutsu CLI is nice because it fixes this UI problem.
leni536
Rebase itself is also often used to work around UI issues of git log to present a "clean history".
Pxtl
Not only that. Git doesn't appear to have any internal link between the hidden pre-rebase commits and the post-rebase commits, which hurts its ability to copy later commits across that rebase.

Yes, you're supposed to avoid moving later commits across a rebase... but the reason you're supposed to avoid that is because git is so bad at it.

saghm OP
I don't think I agree with this take, at least not completely. I tend to commit quite frequently when working on a feature branch in ways that wouldn't be desirable to include in the history of the main development branch, and I take advantage of the fact that rebase lets me clean everything up beforehand into whatever commits I actually want afterwards (which I usually do two separate times, once before opening a review so I can ensure that the diffs help make things easier to read, e.g. if I need to include changes from another branch or make changes in the codebase that aren't directly related to what I'm working on but still are useful for my changes for some reason), and then again after the review is complete if I needed to make additional changes that don't belong in a separate commit (because I find that reviews are cleaner when rebases don't take place during them, and a review that requires more than one or two follow-up commits generally tends to be due to issues that need to be addressed with an offline discussion that I can come back afterwards with structural changes that make the existing diff less relevant). Having to preserve the exact history of commits during my development would be a bad thing in my opinion, since it would either require including lots of small unhelpful commits into the history of the main development branch or discourage committing as often, either of which I think would be a mistake.

Where I agree with your take partially is that the UX for all of this in git is not great, and that ends up meaning that most people don't actually use git in this way. If the process of manually structuring the commits to clean up history on a feature branch were more intuitive, then I'd predict the issues of history-destroying rebases to essentially be moot; everyone would just present the commits for review exactly as we'd want them before review, and then we'd fast-forward merge into the main development branch without any issue. The problem is that doing this sort of restructuring after the fact isn't actually easy to learn how to do because of the poor ergonomics of the git CLI, so it's both tedious and error-prone for almost everyone. My perspective is that most of the concern around messing with history in git comes from being burnt by changes that were not intended by the one making them, and that workflows that avoid it (like merge commits) are essentially a compromise to avoid that risk by accepting a certain amount of cruft in the history of the main development branch. I don't blame anyone for using them, since the problems that make the rebase workflow harder are very real, but I don't think that the fact that rebase changes history is the real issue as much as it provides a mechanism for the actual underlying issues to manifest.

GuB-42
You do whatever you want on your own repository, but as soon as you make anything public, for me, it is here to stay, I consider every push to be pulled by someone else, and if you rebase or do anything to change your history, you have just created a new branch, even if you pretend it doesn't exist anymore using a push --force.

Git is a decentralized version control system. It is effectively a blockchain like Bitcoin but without the consensus mechanism, and just like transactions are final on the Bitcoin network, pushed commits are final in git. You can agree to use one branch over another, but if you are using git as designed (i.e. as a decentralized system), it can be confusing. Merge commits are how you can resolve that confusion.

saghm OP
I guess we just fundamentally disagree with how using git should work. I don't agree at all that using git for a public repo somehow implies that you're committing to preserving every single branch in perpetuity just because the tool can support it. If it's confusing, I'd argue it's from mistakenly inferring that others are conveying intent by publishing public feature branches.
Pxtl
That's my core complaint about git's history-destroying behavior. Git wants you to make a clean history, but it also has awful behavior when you modify history that you've started collaborating with people upon.

It is a fundamental flaw. Either git needs to work better at using the history in all of its warty and real glory (for example offering a separate mutable presentation-layer commit-log in front of the immutable data-layer commit-log), or needs to provide better automation and mapping concepts that allow you handle incoming code that has a different history from the current branch.

GuB-42
Git doesn't what you to have a clean history. Git just stores all the commits in a DAG structure, and then gives you a lot of freedom in what you make of it.

The git UI however is notoriously terrible, so your complain about presentation is probably justified, but it git itself offers facilities to keep a clean history without clobbering branches without changing the fundamentals.

For example, you can decide to make your clean branches only out of merge commits, so if you look only at the clean branches you will have the nice history you expect, but each commit will have a reference to a parallel ugly branch so you can see everything if you want to, without rewriting. To avoir conflicts polluting your clean branch, first merge the clean branch into the ugly branch, resolve the conflicts and do everything you need to do to stay up to date, then merge back into the clean branch, with a nice merge commit message. The clean branches merge commits are your "presentation layer".

It won't be mutable, but mutable anything is a problem in a distributed system like git that gives you availability but as per the CAP theorem, not consistency.

Pxtl
My problem is that so many of git's features feel like they just aren't designed to accommodate history rewriting.

Like if I have branch X and branch Y, and X is 1 commit ahead of Y, but I alter the comment of a commit in Y, now X is one or more commits behind Y and will not recognize identical code-changes as identical.

It gets worse if you squash a commit, where you start getting conflicts during merges and rebases even though the code-changes are the same.

I understand why these problems happen, and the ways to prevent it (don't rebase anything pushed), but it still underscores the fact that git doesn't properly accommodate its own love of rewriting history.

If git had a proper synced graph of history-rewriting actions (commit A was rewritten into commit B) then it would be able to provide better responses when doing a merge or reflist across rewritten branches.

saghm OP
Yep, I don't disagree with you about that. To me, the cost of having to stick with a workflow that prevents it (which you describe) is still worth it to have a clean history without merge commits, but I totally understand that this is a matter of personal preference, and having a consistent workflow for everyone working on a project together matters more. Right now, I'm working on a team that uses merge commits for the first time in a while, and it's definitely taking a bit of time to get used to again, but I'm still committing to it (pun intended!)
hinkley
Can you say more? I use rebase to avoid history destruction/obscuration. Do you mean squash? If so then I agree.
GuB-42
Rebase creates an entire new branch and drops the previous one, it is a form of history destruction.

Commits are actually snapshots of the entire repository, not just diffs, so even if the diff is the same, if the base is different, it is not the same commit. And when you rebase, all the old commits will stay there until you run the garbage collector, and only if they don't have a head.

johnisgood
Eh, squash has its place, too. Sometimes I made a simple typo, so I make another commit that fixes the typo and I squash the last two commits.
Pxtl
Basically, the fact that any kind of tweaking to the history in terms of comments or grouping together related commits into a single commit changes the hashes. This means that git's normally useful ability to check "hey is commit X in the history of both branches A and B" is broken.

That's a huge usability problem with git. Even as simple as a "rebase on merge" or "squash on merge" automation makes it impractical to push your topic-branch and keep working locally on that same branch while your topic-branch is being reviewed and tested, because git doesn't retain any concept of the fact that "this block of commits has been transformed into that block of commits and so you can consider them one-and-the-same".

I'm the git sme at my office and I deeply resent the amount of time I have to spent training juniors and students around git's jagged edges.

Ideally git should have a proper in-repo objects that reify a relationship between rebased/squashed/amended/etc commits and their predecessors and exposes that when you ask things like "hey is commit X in ref Y?" it could say "no, but there is a modified version of that commit".

hinkley
Ah. I know about this. I’m used to people meaning different things when they say history destruction.

There’s also a fun loophole where you can edit other people’s commits when doing a merge and attribute bugs to someone else. I caught someone doing this once (they were terrible at git) on account of I was the one who reviewed the code that got changed, and I specifically looked for that class of bug before approving it. Git blame and the commit history no longer agreed and I was able to show what happened.

This item has no comments currently.