On Tue, Mar 30, 2021 at 2:53 PM Junio C Hamano <gitster@xxxxxxxxx> wrote: > > Elijah Newren <newren@xxxxxxxxx> writes: > > > Using your own words: > > > > "the replace mechanism is about telling Git: when anybody refers to > > deadbeef, use its replacement if defined instead." > > "When anybody wants the contents of deadbeef, give the contents of > its replacement" is what the replace (graft, too) is. > > > git branch didn't do that; it put deadbeef into refs/heads/foobar. > > Yes, but refs/heads/foobar having deadbeef does not have a problem, > as long as you get the contents of the replacement object when you > ask for the contents of deadbeef (or "the object referred to by > the refs/heads/foobar ref"). Your "as long as" is I think the assumption that's violated in the workflow in question. You may have the replace ref defined, but others don't[1]. Neither party has the actual original deadbeef commit[2]. Having deadbeef in refs/heads/foobar leads eventually to creating commits with deadbeef as an explicit parent, as we discussed above. While that's internally consistent, as you point out, can you push your new commit elsewhere without pushing the replace refs too? * If you can, isn't that repository corruption? * If you can't, how are users supposed to understand, debug, and correct the fact that their history is unshareable? Why does `git branch` (in conjunction with one user deciding to fetch replace refs) make it so easy to create a branch that cannot readily be shared with others? [1] Everyone can get the replace refs, but fetch/clone does not grab them by default, and push does not include them by default, so it's multiple manual steps. [2] For the rewrite at $DAYJOB, we'll make it as hard as possible for users to access the original deadbeef commit(s). People who cloned the old unrewritten repo in the past might still have it somewhere if they didn't follow instructions to delete old clones and reclone, but new hires won't have deadbeef and won't have a way to get it.