Hello Junio, Thanks for the insightful response. Firstly, let me add some context, which will be helpful for responding to your comments. This strategy was created at a large organization, where the "main" branch was used as the integration branch for changes made within the organization and for the organization. So whenever an employee needed to make a change, they would start a topic branch off "main" and the topic branch would be later merged or rebased onto "main". When the employee was ready to contribute the change upstream, they would only present the topic branch upstream. The "main" branch was never presented upstream. Release branches were created from the "main" branch to work on releases to production at the organization. Tags were created on the release branches to mark stable and tested versions. Deployments to production were made from the tagged versions. The rest of my response is inline: > So from the upstream point of view, > throwing a pull request for c" (not the original a, b and c) would > be a reasonable way to finalize your work. That way, what you are > offering to the upstream is not an ancient original commits (i.e. a, > b, and c) that you haven't been using at all once you created S and > T. Yes, this is how it's intended to be used. > it is unclear what the eventual > presentation to and adoption by the upstream would look like. As > an upstream maintainer, for example, I do not want to merge S > above to the upstream tree. Presentation to upstream would only involve submitting a pull request for c". Merge S would not be presented to upstream. > how does this help those who have older versions of your > work, *and* built their own changes on top? They would not just > need to update their remote-tracking branch that has your older > version of the work to the latest, but also rebase their work on > top. > > o---o---o---o---o upstream/main > \ \ > \ a'---b'---c'---d'---e' > \ \ > a---b---c-------------S main > \ > d---e your coworker The coworker would either merge their topic branch to "main" or rebase it on top of "main": o---o---o---o---o upstream/main \ \ \ a'---b'---c' \ \ a---b---c-------------S---M main \ / d-------------e o---o---o---o---o upstream/main \ \ \ a'---b'---c' \ \ a---b---c-------------S---d'---e' main > However, once you keep going this way for several rounds, would > the result really be much better than bushy history with full of > reverse merges from upstream? Would it help to add new history > simplification mechanisms and options to help visualize the > history, or do we already have necessary support (e.g. if the > convention for these "merge to cauterize the older versions of > history with the newly rebased history" S and T merges is to > record the rebased history as the first-parent, then "git log > --first-parent upstream/main..main" should be sufficient). Good point. I believe the proposed method has two advantages over using "git log --first-parent": * consider the scenario where the cauterizing merge is not the only merge in the "main" branch - a topic branch from a coworker has also been merged to "main". In that case, "git log --first-parent" would not show the commits from the merged topic branch. * a user unfamiliar with the command-line interface can use a history visualization tool (such as gitk or tig) to obtain a clear view of the differences between the last imported version of upstream and the tip of "main". > The users would benefit to have an easy way, given only T or S, to > get range-diff among (a,b,c) and (a',b',c') and (a",b",c"). I like that idea. It would be great to have a simple git command to display such a range-diff. The command would have to correctly identify the commits. -- Best regards, Aleksander Korzynski