5 ms·
Here's how I address this problem. When I'm developing, but before I create a PR, I'll create a bunch of stream-of-consciousness commits. This is stuff like "
by jawns 5y ago
Here's how I address this problem.
When I'm developing, but before I create a PR, I'll create a bunch of stream-of-consciousness commits. This is stuff like "Fix typo" or "Minor formatting changes" mixed in with actual functional changes.
Right before I create the PR, or push up a shared branch, I do an interactive rebase (git rebase -i).
This allows me to organize my commits. I can squash commits, amend commits, move commits around, rewrite the commit messages, etc.
Eventually I end up with the 2-4 clean commits that your coworkers have. Often I design my commits around "cherry-pick" suitability. The commit might not be able to stand on its own in a PR, but does it represent some reasonably contained portion of the work that could be cherry-picked onto another branch if needed?
Granted, all of the advice above requires you to adhere to a "prefer rebase over merge" workflow, and that has some potential pitfalls, e.g. you need to be aware of the Golden Rule of Rebasing:
https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing https://www.atlassian.com/git/tutorials/merging-vs-rebasing#...
But I vastly prefer this workflow to both "merge only," where you can never get rid of those stream-of-consciousness commits, and "squash everything," where every PR ends up with a single commit, even if it would be more useful to have multiple commits that could be potentially cherry-picked.
- aerovistae 5y ago...what is the golden rule of rebasing edit: googled, "Never rebase while on a public branch" i.e. a shared branch
- notapenny 5y agoIt usually works out fine when you do a `git pull --rebase`, but not everyone does this or has it setup so pulling might have some nasty effects. Generally helps to consider a feature branch as a private branch. Don't push to other people's features without asking, don't fuck up other people's work.
- OJFord 5y agoEveryone absolutely should configure that. (Git config pull.rebase true.) Such an annoying mess it leaves otherwise. And CI is building 'merge branch master', on the master branch, great.
- mkesper 5y agoCombine with git config --global rebase.autostash for your own protection.
- lambic 5y agoAre there any downsides to doing this? Why isn't it on by default?
- OJFord 5y agoI suppose just the usual 'rebase vs. merge' - i.e. if there are conflicts to resolve they will be dealt with commit-by-commit in the usual way when rebasing, whereas without the option set they will be dealt with all at once 'merge-style'. I happen to think that's a feature, but I know some don't like it. I think there's less argument in favour of merge than usual with pulls though - since it's much less like a semantic merge to begin with for git-merging to preserve a history of. I'm certainly not aware of any objective downside/gotcha/'oh but it doesn't work when...', no. The docs only add that you might further want to set it to `interactive` or `merges` rather than `true`, for the effect of rebasing with those options: https://git-scm.com/docs/git-config#Documentation/git-config.txt-pullrebase https://git-scm.com/docs/git-config#Documentation/git-config...
- formerly_proven 5y ago> Why isn't it on by default? Because git was written primarily for the Linux kernel and the defaults reflect that. The workflow of the Linux kernel is completely different from what most people outside of it do with git. "git pull" is used for opposite purposes in both worlds.
- heurisko 5y agoI think it's the usually public vs private branch issue. If you're merging a public branch with another public branch, then if you a rebase, rather than a merge commit, then you mess up the history for anyone has pulled that branch. For private branches that isn't an issue.
- SnowingXIV 5y agoYes, if you're going to rebase, rebase your feature branch. Do not do it on the shared staging/dev etc.
- matticusrex 5y agoThe only problem I have with this workflow in the command line is that I would like to be able to split changes to the same file across multiple commits. I think some GUI tools enable this, anyone know about it?
- arilotter 5y agoWhen you're doing your interactive rebase, find the commit you'd like to split - choose "edit" for that one. Then when you reach that point, you can do `git reset HEAD^1` to bring those changes back onto your staging stack, and make as many commits as you need.
- tuckerpo 5y agoI do this via git add -p which breaks your changeset down into atomic patches that you can either add, skip or delete before making a commit. You can turn one file change into many commits this way, if need be.
- btschaegg 5y agoHave a look at `tig`. It's even included in Git for Windows now and does this reasonably well. Only the keybindings are a bit weird if you're not accustomed to Vim bindings: - Open tig - Change into the staging view with `s` - Select your file using the arrow or `j` and `k` keys - Press Return to show the diff - Navigate to the line(s) in question with `j` and `k` (arrow keys will switch files) - Stage parts with `1` (single line), `2` (chunk parts), `u` (chunks) or split chunks with `\` - "Leave" the diff with `q` - You can find the keybindings with `h` in the help screen, which also uses Vim keys -- like manpages usually do
- mariusor 5y ago"s" is status view, which you can also get at by running "tig status" directly. "c" is staging view. > - Stage parts with `1` (single line), `2` (chunk parts), `u` (chunks) or split chunks with `\` You can also revert a chunk or file by using "!". Sometimes this is very useful.
- elpakal 5y agoI do this (kind of too), but instead of an interactive rebase I just do a `git reset --soft <target_branch>`, where target_branch is the local (and up-to-date) copy of my target branch. That gets me one clean commit that I can force push up to replace my branch @ remote. (This works for me because auditing commit history is not important where I work, if it were I would organize commits better.)
- dopidopHN 5y agoI first did rebase, and after a while I realized I was not getting much of it since I mostly wanted to merge everything down to a single commit.
- andrewzah 5y agoThis is the ideal workflow for me since I think merge commits clutter up the log, but it falls apart if people aren't consistent in following it. *glances and $corp git repo and sees 'updates' 'fix' 'updates'. Sigh.
- Consultant32452 5y agoI've always been fond of the "WIP" commits.
- fatnoah 5y agoThis is very close to my approach. I work in a private branch and make many commits along the way, but then organize it to tell a coherent story for the actual PR.
- spacechild1 5y agoI do the same. A clean and logical history helps other people understand your code and might consequently increase the chances of getting it merged.
- nyanpasu64 5y agoI do the same thing generally. In fact I generally find multiple mistakes or changes to be made, reading over my own code before merging, requiring figuring out which commit to merge my changes into (git absorb helps in the easy cases) and even more rebasing, or giving up and adding an extra commit at the end. I see some people whose projects (Furnace Tracker, PipeWire, previously Famitudio) seem to make progress very quickly without getting noticeably slowed down by technical debt, despite sloppy programming and unorganized commit logs (push-to-head). Meanwhile I move slowly, dread reviewing hundreds of lines of my own code, and produce technical debt (regrets) anyway, not as many surface-level lintable errors but plenty of entrenched mistakes. I wish I could move faster, but instead struggle to make progress.