4 ms·
The reset part seem superfluous, most of this can be handled via rebasing. In fact, this is exactly what we do at <day job>. Much like the thesis of this artic
by dljsjr 5y ago
The reset part seem superfluous, most of this can be handled via rebasing. In fact, this is exactly what we do at <day job>.
Much like the thesis of this article, the goal is to have a set of well organized commits so that when it comes time to do a PR review, you have 1-3 logical units of change and it also improves the ability to do reverts.
But you can very easily do this just by rebasing instead of resetting and re-committing.
In particular, `git commit --fixup <ref>` and `git commit --squash <ref>` are extremely useful for this during the "WIP" stage as well as when handling PR comments, and these are things that I only learned about in the last 6 months. I would recommend doing a google search on "fixup commits" to learn more about them. I enjoyed this article: https://www.mikulskibartosz.name/git-fixup-explained/ https://www.mikulskibartosz.name/git-fixup-explained/
Yes, rebasing is scary if you're new to git, but it does everything in this article in a way that's much cleaner and once you learn how to use it effectively you'll feel like you have super powers. It's worth taking the time to learn.
- okl 5y agoRight, I don't think rebasing is that daunting if you take a few hours to practice. It's time well spent. Sometimes you can even create empty commits (--allow-empty) up-front (if you already know about all the things that have to be changed) and fill them via fixup/rebase --autosquash
- dljsjr 5y agoAfter learning about fixup and squash commits, I started typing `git rebase -i --autosquash` so frequently that I made an alias for it. It has totally changed the way that I work. You get to have the best of both worlds; commit early, commit often but then also having nice and tidy PR's and histories.
- okl 5y agoMy aliases: alias.c commit alias.cf commit --fixup alias.cm commit --message alias.co checkout alias.f fetch -v -p alias.par pull --rebase --autostash alias.ri rebase --interactive --autosquash --autostash alias.rim rebase --interactive --autosquash --autostash master alias.s status alias.l !git --no-pager log --oneline -n10 alias.pf push --force-with-lease alias.bs !git --no-pager diff --stat master..HEAD alias.p push alias.alias !git --no-pager config --get-regexp alias Sometimes I get the feeling that my job isn't programming but managing text snippets (diffs).
- evanrelf 5y agoYou can also enable auto-squash by default: git config --global rebase.autoSquash true
- jcranmer 5y agoThe one thing I wish were easier would be breaking a single commit into two commits. Edit: to be clear, I know it's possible by using git reset... but I'd much rather have something like git add -i that interactively shifts changes from the commit itself and moves them into working directory-only changes.
- dljsjr 5y ago1. `git rebase -i` to the commit before the one you want to split 2. mark the commit you want to split as an `edit` 3. remove the file(s) you want to edit from the index so that it's part of your working tree 4. use `git add -p` to stage the hunks you want in the first commit (assuming you want to split commits in a single file) or just commit the files you want in the first commit first, second commit second.
- okl 5y ago> 4. use `git add -p` I strongly recommend tig
- dljsjr 5y agolazygit is also great. VS Code also makes it easy to stage hunks in the editor if you like to stay in your editor; in the diff viewer from the Git view you can highlight the lines you want to stage and right click -> stage selected ranges. I've never used tig. I'll look at it.
- cerved 5y agowhat's the advantage over partial?
- okl 5y agoGive it a try and compare. tig lets you either stage hunks ('u') or lines ('1'). You can also adjust the context ('[', ']') and split chunks ('\') and revert chunks ('!') all from the same view.
- sandgiant 5y agoRebase is great, but it's usefulness really depends on the commit history. If your branch consists of 10 commits of trying various things, then the sum of changes in all the commits can easily become significantly larger than the final branch diff. In that case resetting is orders of magnitudes faster than fiddling with rebase.
- okl 5y ago> If your branch consists of 10 commits of trying various things Use fixup commits.
- GauntletWizard 5y agoThat's the point of squashing commits - Many of your changes will ultimately pare down into just a few logical thoughts, adding function X to feature A, then using that in function Y in feature B etc... It's not something that comes for free, of course, but if you make many small commits and try to get each file to compile each time you can often basically just squash by file or directory.
- dljsjr 5y agoI would reject a merge from a branch that does more than one thing at a time as you've described during code review. It's okay to have a branch that does a bunch of things at the same time, but come time to merge back to `main` this should be broken up in to several different PR's. I would probably branch off my branch for each logical change I wanted merged and use `rebase -i` to wholesale drop commits that I didn't want on the branch anymore. This is also an example of where stacked diffs are far superior to PR's but that's a separate issue.
- ninkendo 5y agoNothing in sandgiant's post implied that there's more than one thing happening in the branch. Quite the opposite actually, they said that the final diff could be much smaller than the sum of all the small WIP commits along the way. It could be that after hours of digging, you found the real bug was a typo somewhere, and the final diff may be just a 2-line change, where one of the WIP commits was rewriting the whole auth layer because you were chasing a dead-end.
- cerved 5y agoFix-ups are nice. I developed a script that takes the all staged content and breaks them up into separate fix-ups that fixup the last commit that changed those lines. I find it pretty handy
- karl42 5y agoThat sounds much like git absorb. See https://github.com/tummychow/git-absorb https://github.com/tummychow/git-absorb
- cerved 5y agothanks I didn't know about that maybe, but it's probably much simpler. It's just a small bash script that runs git blame twice for each line in the index and creates a fixup per commit found
- atq2119 5y agoYes, rebase is awesome and every Git user should learn about it. But why not both? When I'm working on a more complex patch series, it's not uncommon for me to have a bunch of already cleaned up, or semi-cleaned up commits on top of the remote branch I'm working against, and then a bunch of random garbage "WIP" commits. Something that often happens is that I `git reset` not to the upstream branch but to my most recent clean commit, take the resulting changes apart into individual commits (often, some of them will be squash/fixup as I discovered a bug or missing piece of earlier work) and then `git rebase` with `rebase.autosquash` enabled in my global Git config.
- dljsjr 5y agoSure. I do that as well. But this article was advocating for using a soft reset to replicate what is ostensibly the built-in fixup mechanisms from interactive rebasing.