I’m not a fan of doing this with git, since it deletes commits. True, for work-in-progress stuff (like a pull request) it’s usually ok to delete commits like this, but every once in a while you’re going to want to go back to an old commit, and with this you won’t be able to.
That’s one reason I really like mercurial’s implementation of changeset evolution as implemented in the evolve extension. I’ll be really excited when evolve finally makes its way into core mercurial and bitbucket officially adds support for it. I’ve been beta testing bitbucket’s implementation for a couple months and it’s really been a night-and-day improvement for the quality of my pull requests. All without sacrificing history.
Mercurial’s versioned history always seemed like a good idea to me.
I typically have a working and a squashed branch to handle this scenario:
I actually have a git command to handle the checkout + merge --squash + commit steps:
checkout + merge --squash + commit
You might not want to do it for everything, no. I agree that some PRs it makes sense to use multiple commits. But for others I think squashing makes sense. For example, I provided a small PR to ring that went through 12 comments and stood at 5 or more commits, each changing the same lines in different ways until we arrived at something agreeable. I don’t think it would have been useful to keep all those commits for what’s essentially a single bugfix with ~20 lines of code touched.
In this case, hg fold can be used to mark a single commit as the replacement of all previous 5 commits. The reverse can also be done with hg split, which will mark a single commit as being replaced by multiple other commits.
The nice thing of recording the replacement operations is that you still have your exact history, should you really need it, just hidden by default and not pushed/pulled by default. Also, hg can use the meta-history in order to convey properly to new repos how commits should be moved around. No need to manually reset clones!
That is quite nice! So, in the bisect case, you’d be able to high-level bisect on folded feature requests, then when you’ve found the offending feature, do more fine-grained bisect on the individual commits making up that feature? That would be really nice, and I’d love it if git had something similar. (I don’t see us moving off GitHub in a hurry.)
you’d be able to high-level bisect on folded feature requests, then when you’ve found the offending feature, do more fine-grained bisect on the individual commits making up that feature?
There isn’t an automatic UI for this, but it would be pretty easy to build that with a couple of hg commands. If your bisect points to a folded revision, yeah, you could easily jump to the pre-folded history and keep bisecting (to wit, hg update -r 'precursors(.)' will take you to the commit(s) that the current one is replacing).
hg update -r 'precursors(.)'
I believe the commits are still present in both the local and the remote repository, they’re just not linked to any branch anymore.
They will get garbage collected by git eventually. Also I don’t think you can easily see the github’s reflog to find the old commits.
This is the thing that annoys me most with github. In the sense that I’d much rather receive a diff. The work flow annoys me to no end. I’m not sure about the best answer for this, it seems to me like there’s no clear best answer. I’m confused and angry so I’ll just repeat my argument loudly until it’s true.
If you actually write your commits in a way that generates a clean history, the github workflow for reviews/etc is alright (commenting on lines of commits works pretty nicely even if it is somewhat hidden).
If you’re going to go through all this trouble, wouldn’t the merge commit that is created if you Merge the PR in GitHub’s web interface also annoy you?
Current project workflow after CircleCI is done and the code review was done:
Rebase on Master
Squash branch into one commit.
Force push branch. (<- this rings my alarm bells)
git merge –ff-only my-branch.
Prime directive is: Don’t touch the green merge button ever.
Why not just git diff the two branches? Git diff is basically a “Single patch” view of the combined changes, but you can still keep the history.
Better to use --force-with-lease, which will enforce that you overwrite what you think you’re overwriting rather than (potentially) overwriting work that others may have since pushed to the same branch.
Personally I don’t see the value in doing this, provided the commits are descriptive and each leaves the tree in a working state. The value of having git history at all is a) being able to git blame and see what a specific line was written to do with b) being able to git bisect to figure out what introduced some subtle bug that you didn’t catch at the time. Both of these things are made better by having small granular commits.
I think it’s much better, from a bisect stand point, to only have commits that take the tree from one working, tested state to another working, tested state. If you didn’t test a particular commit in isolation, such that you can say with certainty that it stands alone, I don’t think it belongs in the history.
There’s tested and there’s tested. E.g. if you have a month-long UAT process you wouldn’t want that to be a single commit. I would agree that every commit should be a state that compiles (otherwise it’s useless for bisection), and perhaps should pass a local unit test run as well, but I think they can still be a lot more granular than the things you’d send a github PR for.