> Further a force push after rebase is destructive because there is no reflog on a remote bare repo. The corollary is that force pushing deletes commits that are impossible to recover with any “regular” git command.
That's somewhat true, there's a whole section about this in my post. But in that case it's not the rebase that is "destructive", it is the forced push. And even that is not destructive as in "unrecoverable". Those changes are not impossible to recover. I can undo my rebase and force-push it again. So can my colleagues working on the same branch. Yes, it's impossible to recover from the bare server's perspective, but this has nothing to do with my original claim that "rebase is not destructive by default".
> Then just simply say things can be undone with the reflog.
I did. That's why I have problem with the word "destructive", because the whole meaning of that word is that something cannot be undone. This was the main point I was trying to make.
>> moving a branch does not "change" the history (= the commit graph). > It will point to an entirely new commit graph. This is a change. > The commit graph you refer to may very well be orphaned (ie deleted) at this point.
No, the commit graph doesn't change when moving a branch. "git reset" will move the branch and not change the graph of the commits in any way. That's why "git reset" is as destructive as git rebase. Yeah, git gc can then actually alter the commit graph (i.e. drop orphaned commits), but that's another point I've explained and warned about in my post. It doesn't affect the non-destructivity of git rebase or git reset.
But maybe you're just seeing the reachable commits as "the commit graph" and the reflog as something special, leading to our misunderstanding. I don't - both reachable and unreachable commits are part of the commit graph internally.
> That's why I have problem with the word "destructive", because the whole meaning of that word is that something cannot be undone.
The only problem with this definition is that it is a bit useless, nothing is destructive. Even without the reflog (or stash) you can always restore from backup, or even an ad-hoc locally cloned repo (git makes this especially easy). I agree it's good to know you can undo things and what the built-in facilities are, but it doesn't further elucidate the issues with rebasing as a workflow.
The original statement:
>> Rewriting history with rebase is a destructive operation and I would never advocate for it to juniors. Merges are much more straightforward because they follow the git mental model of acyclical directed graph.
Is clearly in the context of an ongoing workflow involving rebases. Doing an operation and then immediately or even later just undoing it by reverting from the reflog or some old ref is not what is referred to, nor is it relevant to their objections (obvious as they are comparing it to merges).
rebase is a destructive operation from the perspective of the branch the moment you do it, and then when you push it becomes someone else's problem very quickly. They are essentially on the conveyor belt to be destroyed. 30 days isn't even that long, and hoping that your coworkers didn't blow away their local repos doesn't scale.
I also don't see how quibbling with the wording "rewrite" vs "alter" is useful.
>> It will point to an entirely new commit graph. This is a change. > The commit graph you refer to may very well be orphaned (ie deleted) at this point.
There's no precise generally agreed upon definition of "commit graph" in git near as I can tell, even the commit-graph caching facility takes a --reachable option and this is commonly how it is used with many tools, and in books "commit graph" has often been used to refer to a graph starting from a specific commit (as in "git log --graph displays the commit graph", "...when using git log -g to examine the reflog instead of the commit graph ..."). Having said that I won't argue the point about wording and I don't disagree your definition is valid. But I don't think you can claim some authority without a mutually agreed definition. This is also an odd time to start being pedantic.
The actual brass tacks on this is that moving a branch is a change in the mutable repository state. This hangup on the commit objects being immutable while "only" the pointers change is a meaningless distinction for the matter at hand. Once you get to the most common use case of git, using shared repos, those commit pointers (branches/refs) are what get published, and that is what defines the shared constitution of "the commit graph", so they are what matter.
> But maybe you're just seeing the reachable commits as "the commit graph" and the reflog as something special, the reflog as something special
Well it is special. It's repo specific, not shared, and non-essential to the normal operation of git.
But that's not the objection. The main one can be boiled down to, what gets shared and why it gets shared and how the graph looks to clones is more important than defining what is the graph in a private repo. Especially when making someone understand the consequences of rebase vs merge.
> I don't - both reachable and unreachable commits are part of the commit graph internally.
I mean this isn't wrong for one general definition of commit graph, but it isn't always a terribly useful definition.
git itself puts virtually no restrictions on this internal commit graph as defined. A git repo/packfile can contain any arbitrary collection of commit objects, you can have two completely unrelated set of trees with commits. You can clone the linux kernel source and then say fetch react into the same git repo, and now you have a disconnected commit graph. This is cool and all and there are some practical applications for it but I don't see it how it is related to the issue of history destruction/rewriting in the context of a shared rebase workflow. Thinking in terms of reachable, strictly non disconnected subgraphs is often more useful.
That's somewhat true, there's a whole section about this in my post. But in that case it's not the rebase that is "destructive", it is the forced push. And even that is not destructive as in "unrecoverable". Those changes are not impossible to recover. I can undo my rebase and force-push it again. So can my colleagues working on the same branch. Yes, it's impossible to recover from the bare server's perspective, but this has nothing to do with my original claim that "rebase is not destructive by default".
> Then just simply say things can be undone with the reflog.
I did. That's why I have problem with the word "destructive", because the whole meaning of that word is that something cannot be undone. This was the main point I was trying to make.
>> moving a branch does not "change" the history (= the commit graph). > It will point to an entirely new commit graph. This is a change. > The commit graph you refer to may very well be orphaned (ie deleted) at this point.
No, the commit graph doesn't change when moving a branch. "git reset" will move the branch and not change the graph of the commits in any way. That's why "git reset" is as destructive as git rebase. Yeah, git gc can then actually alter the commit graph (i.e. drop orphaned commits), but that's another point I've explained and warned about in my post. It doesn't affect the non-destructivity of git rebase or git reset.
But maybe you're just seeing the reachable commits as "the commit graph" and the reflog as something special, leading to our misunderstanding. I don't - both reachable and unreachable commits are part of the commit graph internally.