[HN Gopher] Take Advantage of Git Rebase
___________________________________________________________________
Take Advantage of Git Rebase
Author : HieronymusBosch
Score : 103 points
Date : 2022-10-06 13:07 UTC (9 hours ago)
(HTM) web link (about.gitlab.com)
(TXT) w3m dump (about.gitlab.com)
| rmetzler wrote:
| I was waiting for ,,Gitlab releases a UI for rebase -i in MRs".
| dnsmichi wrote:
| Thanks, great idea. Added a comment into the feature proposal
| in https://gitlab.com/gitlab-
| org/gitlab/-/issues/273250#note_11... - suggest upvoting and/or
| subscribing to notifications.
| zwieback wrote:
| Years ago I really liked rebase, now I never use it. I don't know
| why, though, one of those mysteries of the brain.
| secondcoming wrote:
| Been using git for 10 years now, never rebased, never had an
| issue.
| goalieca wrote:
| You've never used gerrit then. That tool is entirely designed
| around rebasing with merges as a rare event.
| recursive wrote:
| Nor have I heard of it. (not OP)
|
| There are probably tools built around merging too.
| goalieca wrote:
| Gitlab and github are built around merge-requests and
| gerrit around rebasing/amending. I strongly prefer
| gitlab/github workflows.
| chris_wot wrote:
| You've never lived.
| ayewo wrote:
| Can't tell if you are joking or not, but if you are not
| that's a bit too mean. At the end of the day, they are merely
| tools.
|
| > _You 've never lived._
| chris_wot wrote:
| I use it all the time.
| Jwarder wrote:
| I think it depends on what problems you want git to solve for
| you.
|
| Some people like having the context from the complete the
| history of little commits without the risks of rebase breaking
| something.
|
| Some people like using rebase to group all changes needed for a
| feature into isolated(ish) commits.
|
| Some people just like the aesthetics of a straight master
| branch without the clutter of little "corrected typo" or "fixed
| bug for real this time" commits.
| chriswarbo wrote:
| Been using git for 15 years now. Occasionally rebased, usually
| had an issue ;)
| placatedmayhem wrote:
| Rebase has become so integral to my workflow, it's hard to
| imagine living without it. I intentionally avoid merge commits,
| including configuring git pull to rebase rather than merge. I
| find it so much easier to commit a bunch of tiny iterations while
| doing local testing, rebase and squash them, then post them for
| review. As a bonus, I frequently push after each of those small
| commits to a feature branch so I don't have to worry about losing
| work if my drive dies.
| agumonkey wrote:
| then there's autosquash and similar
|
| honestly the commit graph as a first-class value yields a lot
| of ideas in my mind, we should be investigating compute at the
| subtree layer more often.
| rrwo wrote:
| > Rebase has become so integral to my workflow, it's hard to
| imagine living without it.
|
| Same. I use it to reorganise branches before submitting change
| requests or merging:
|
| - Combing or splitting commits so that each commit contains a
| small unit of a logical change
|
| - Reordering commits to related changes are near each other
|
| - Reordering commits so changes that are depended on by later
| commits occur earlier.
|
| - Rewording commit descriptions to have a lengthy explanation,
| if needed
|
| - Removing small commits that fix minor typos
|
| It's a great way to turn the commit history of a project into
| one of logical changes, rather than a simple temporal log of
| every change.
|
| (I had a colleague who was so used to CVS and couldn't get his
| head around not using version control as a time tracking
| device.)
| rubyist5eva wrote:
| Personally, I actually stopped using rebase or advocating it's
| use (because noobies mess up their history all the time with
| it). I just commit whatever, then when the code is merged to
| trunk/dev/master/whatever I use `merge --squash`.
|
| Reviews are very rarely happening on the commit level, so
| having lots of small "meaningless" commits (lint fixes, fix
| spec, add thing) hasn't been an issue but having squashed merge
| commits (effectively a rebase that squashes everything) has
| made release management so much easier for our team.
|
| It also has the benefit of just less cognitive overhead of
| micro-managing my feature branch commits that are WIP or
| currently in-review.
| dabears wrote:
| This is my workflow as well, it's great. Github is configured
| so merging a PR into master will automatically produce a
| squashed commit.
|
| My rule of thumb, always rebase unless you hit a series of
| merge conflict while rebasing. Then either merge, or squash
| your branch then re-run the rebase.
| rubyist5eva wrote:
| We require linear history on our shared mainline branches
| so the squash workflow works great for us using Github as
| well. Another benefit is the "show changes since last
| review" option when reviewing a PR - it's been a while but
| I'm not sure if this is possible with a rebase-based
| workflow.
| jokab wrote:
| Thanks. I thought it was just me.
| gregmac wrote:
| > Rebase has become so integral to my workflow, it's hard to
| imagine living without it
|
| I'm the same. I commit frequently. A lot of those end up being
| `--amend`, but a lot of time I will rebase and
| squash/reorder/etc. In fact I'd say the majority of time I push
| changes I've rewritten my local history at least once.
|
| According to any git history you'd find from me on the server,
| you'd think I never accidentally commit syntax errors, break
| unit tests, and that when I do big structure changes or
| refactors I get it the way I want it on my first attempt.
|
| > including configuring git pull to rebase rather than merge
|
| It annoys me a bit this isn't the default -- at least for teams
| that work from a single centralized git repo (eg: almost all
| corporate dev, and the majority of open source). I've done it
| for years and have never had any issue with it.
|
| It doesn't rewrite anything but your local (non-pushed)
| history, which is totally fine. (Unless you are working with
| multiple remotes, in which case it causes chaos, which I think
| is why it isn't the default).
|
| Are there other drawbacks?
| robertlagrant wrote:
| This might be obvious, but it's worth checking out git commit
| --amend. Then you can be regularly committing, but to the same
| commit.
| usr1106 wrote:
| --amend if you have a modification to your most recent
| commit.
|
| --fixup if you have a modification to an earlier commits
|
| rebase --autosquash amend the fixup(s) to the commit(s) they
| belong too.
|
| (Of course you need to know what you doing. Otherwise you
| create conficts tedious to resolve in the rebase)
| dnsmichi wrote:
| Depending on the workflow and collaboration in branches in
| teams, amending may not be ideal. Amending changes to an
| existing commit will generate a new sha checksum, thus
| resulting in a diverging history if the branch is often
| pushed to the remote Git server. That's one of the rare cases
| where "git push --force" makes sense but also requires
| awareness for other collaborators on the branch - they need
| to run "git fetch && git reset --hard origin/branchname"
| every time, and best "git stash" to temporarily remove any
| local changes, with running "git stash pop" afterwards.
|
| One reason to regularly push commits can be to trigger CI/CD,
| security scanning and dev/staging deployments or review apps.
|
| GitLab team member here - before joining GitLab in 2020, I
| was a Git/GitLab trainer.
| https://www.netways.de/en/blog/2018/05/24/releasing-our-
| git-...
| tspike wrote:
| I've completely replaced my use of --force with --force-
| with-lease. It does the same thing, except it will abort if
| the upstream branch has been updated since your last pull.
| This pretty much prevents the concerns about clobbering
| others' work.
| dnsmichi wrote:
| After reading this comment about "git push --force-with-
| lease" in https://stackoverflow.com/a/53011907/1821348 my
| workflows with "git fetch" first would not work with "git
| push --force-with-lease", behaving as if "git push
| --force" was run. Theoretically - I need to do some
| testing here.
|
| Thanks for the pointer into learning something new :)
| robertlagrant wrote:
| For sure, it doesn't work with every workflow. But I think
| it would for the OP's described workflow.
|
| And I am currently waiting for my GitLab backpack for
| contributing something (very small, but apparently it
| counted!) so thank you to the team for that!
| dnsmichi wrote:
| Thanks for sharing your ideas, appreciate the thoughts to
| learn new perspectives :-)
|
| And also thanks for contributing, every contribution
| counts and helps :-) Maybe see you at a future hackathon
| :) https://about.gitlab.com/community/contribute/
| shagie wrote:
| --amend would interact with the remote system poorly if
| there's a push with each commit.
| sjburt wrote:
| You have to force push, but you have to do that when
| pushing a rebased branch as well. In either case it's a
| history rewrite. It's not a big deal unless other people
| have pulled that branch--if they have they will need to
| reconcile things on their end as well.
| DrBenCarson wrote:
| Easily the most underutilized and poorly understood part of the
| typical git workflow
| boleary-gl wrote:
| I don't know if Christian would go this far, but I actually put
| this into my ~/.gitconfig so that I'm _always_ rebasing
|
| [pull]
|
| rebase = true
|
| edited for line spacing
| davecamp1717 wrote:
| Yeah, I wish this was the default functionality in git, to me
| it never makes sense not to want to rebase when pulling.
| augusto-moura wrote:
| Just a nit on the HN comment, you can indent the lines 2 spaces
| so that it shows up as a code block, it should maintain the
| correct spacing/line wrapping and it uses a monospaced font as
| well like this
| boleary-gl wrote:
| Thanks - today I learned
| dnsmichi wrote:
| Today I learned, thanks a lot!
|
| Created a MR for the Developer Evangelism Hacker News
| handbook to add this formatting tip, and some more
| https://gitlab.com/gitlab-com/www-gitlab-
| com/-/merge_request...
| dnsmichi wrote:
| You are more brave than I am - I have it explicitly disabled
| :-) https://gitlab.com/dnsmichi/dotfiles/-/blob/main/.gitconfig
|
| When I pull and it runs into a merge conflict, I want to see
| that error/log on the CLI. Reason: Sometimes the automated
| pull-rebase takes a very long time to resolve conflicts after
| each step. I prefer to first run git fetch
| git diff branchname origin/branchname
|
| and then decide my strategy :)
|
| Bit off-topic but since we share .gitconfig tips - I upgraded
| to a recent Git version and enabled the "git push" option to
| setup tracking automatically. No more "git push -u origin
| branchname" actions.
| https://gitlab.com/dnsmichi/dotfiles/-/blob/main/.gitconfig#...
| [push] autoSetupRemote = true
| silverwind wrote:
| `pull.rebase` should be the default just because it avoids the
| problem of merge commits.
| greatpostman wrote:
| Wow did not know this existed. I'll add it to my config
| MilStdJunkie wrote:
| In my personal experience rebase made ISO9000/AS9000 gatekeepers
| twitchy. Even to the extent that they'd tell the Overlords "Do
| everything in Perforce, or else".
|
| And then the Overlords shut down all the VCSs because "this isn't
| a software company". Then everyone sneaks around using weird
| homebrew portable tracking widgets, or, more often, just gives
| up.
|
| Is rebase handy? Oh yeah.
| tuckerpo wrote:
| I love rebase. It allows for a Draft PR workflow where you can
| have your WIP out in the open for a big project, and then clean
| it all up via rebasing right before asking for reviews. Just
| don't rewrite history on master. :^)
| dbbk wrote:
| Every PR we have in GitHub is merged with a squash, so I'm kinda
| missing the value proposition here. Is it really crucial for each
| commit to be a nice clean unit of work?
| throwaway_au_1 wrote:
| Never understood the appeal of squash commits at merge time,
| assuming the PR contains atomic, logical commits (all bets are
| off if your team's PR process accepts ad hoc commits..). You
| lose the utility of git bisect, conventional commits, etc, and
| also have larger, noisier commits forming your
| history/documentation. Is there a benefit to squash commits
| other than allowing developers to forget about that as they
| work? I may be biased against squash commits as I have spent
| enough time diving through garbage commit history to figure out
| bugs/Chesterton's fence that good commits as documentation
| appeals to me.
| ivanche wrote:
| I much prefer to see one squashed commit over an endless
| stream of "fix typo", "small fix", "fixup", "forgot XYZ"...
| tcoff91 wrote:
| Don't approve PRs that have those commits.
|
| A PR doesn't necessarily have to be a single commit to be a
| good PR. Sometimes, it makes sense for a PR to have several
| atomic commits.
|
| Those tiny messy commits should be fixed-up into the atomic
| commit that they are fixing.
| phailhaus wrote:
| > assuming the PR contains atomic, logical commits
|
| This is impossible to enforce or guarantee at scale.
| Squashing PRs, though, is practically fool-proof: PRs already
| represent a single, atomic unit of work that passes all CI
| checks and is safe to merge. No such thing is true (or should
| be!) of individual commits within that PR. Whether we like it
| or not, a branch commit really only represents a "save point"
| for a developer.
| kbr- wrote:
| What you say is impossible, we pretty successfully apply at
| ScyllaDB (see
| https://github.com/scylladb/scylladb/commits/master).
|
| I'm not sure 100% of the commits compile & pass all tests -
| there may be some mistakes - but generally we're in a
| pretty good state, and the clean git log is being
| successfully used for bisecting.
|
| If you want even larger scale - if I understand correctly,
| the Linux kernel practices a similar thing, which is where
| we got this practice from (ScyllaDB founders came from
| kernel development). And since Git was originally created
| to help developing Linux - that's where you want to look
| for good practices.
| WorldMaker wrote:
| You can get the same guarantees without squashes with {log,
| bisect, blame} --first-parent and merge --no-ff (force all
| PRs to make merge commits). You can preserve more of the
| graph and use it to revisit "inside" of PRs when necessary.
| tcoff91 wrote:
| So much this. Everyone needs to learn about --first-
| parent, it makes git log, git bisect, etc... so much more
| powerful and prevents people from just squashing PRs into
| giant mega-commits that make the history so much less
| useful.
| WorldMaker wrote:
| I keep joking that all we need is one good Git GUI to go
| viral that defaults to --first-parent in every view and
| we might eventually convince more people they don't need
| to squash/rebase as much. One of these days I may even
| take the joke far enough along to prototype something.
| debaserab2 wrote:
| You don't lose that much utility of git bisect unless your
| PR's are typically large.
|
| One thing squash and merge does is make reverting trivial.
| tcoff91 wrote:
| You can revert a merge commit.
| dnsmichi wrote:
| GitLab team member here, putting my personal hat on - from my
| experience in using different Git workflows since 2009, a
| smaller clean unit of work can help with debugging and
| troubleshooting. It also provides a way to new team members and
| contributors to understand the thought process and ideation to
| implement a new architecture, apply performance fixes, add
| documentation, work with tests, additional fixes, until its
| final release. Most of this can be tracked within a MR/PR and
| the history of code reviews, etc. - even after the merge and
| squash and Git branch delete, not trying to argue with this
| functionality. :)
|
| From the Git CLI, without any reference to Git* platforms, it
| is not so obvious when searching for a commit that introduced a
| bug, e.g. using "git bisect" for binary search. Reading a
| 10,000 lines git diff can be harder than a smaller commit that
| also explains the reasoning in the commit message. Speaking
| from own experience and programming mistakes in a small team,
| focussing on clean commits and a good history tremendously
| helped in stressful debug situations. Until you hit a compiler
| regression bug, but that's a different story then ;)
|
| I'm personally still very fast on the Git CLI, but I also know
| that there are a variety of CLI and UI tools out there that can
| help with analysing large Git commits. Potentially in the
| future also AI assisted that tell us which change a diff caused
| a performance regression in a release 5 months later. Or we
| don't need it at all because Observability driven development
| enabled to see these problems before merging and code reviews,
| e.g. the memory leak but only when DNS fails. True story from
| ~2016, more in my KubeCon EU talk at
| https://www.youtube.com/watch?v=BkREMg8adaI and project at
| https://gitlab.com/everyonecancontribute/observability/cpp-d...
| mixmastamyk wrote:
| If your merge request is gigantic, that's the problem. Easier
| to keep those focused than obsess about every commit.
| dnsmichi wrote:
| True, thanks. Some workflows can require larger merge
| requests, having the platforms and tools that enable
| smaller iterations help reduce (or eliminate) them though.
| agumonkey wrote:
| you keep the feat branch but only add single merged commit to
| master ?
| giancarlostoro wrote:
| I think it really depends on whose doing the commits, I've
| mostly worked with people who wont commit things that don't
| work so you see a lot less commits than you would expect. I
| prefer commits to be iterative and I prefer to see that if
| possible. I rather see 100 commits across dozens of files per
| commit vs 1 commit for 500 files.
| P5fRxh5kUvp2th wrote:
| plus, you can tell who doesn't use git bisect because they
| prefer a single large commit across 500 files to keep history
| clean.
|
| As opposed to a series of small commits, that would make git
| bisect actually useful.
| mixmastamyk wrote:
| Your features are not broken down enough if one ticket
| requires hundreds of changes.
| giancarlostoro wrote:
| This is a solid argument. Except in cases where you're
| upgrading everything in a small to mid sized codebase
| that needs a major dependency updated that affects
| everything from syntax to other things, and cannot be
| done discretely.
| dmatech wrote:
| Why can't we just have some kind of "virtual squash" where
| the commits are preserved, but they're grouped together so
| you could view it as a single squashed commit if that's
| preferable?
| lixtra wrote:
| Why not keep commits as the atomic element and use
| (release) tags if you want a coarse overview what
| happened?
| wnoise wrote:
| That's a semi-linear history merge.
| warmwaffles wrote:
| Depends on the situation entirely.
|
| If I see a ton of commits like "fixing formatting" or "oops",
| I want those squashed away into proper commits.
|
| If the changes you make are atomic in their own right and I
| can check out that commit, compile it, then run tests, and it
| passes. That's perfect. It works good for git-bisect, but the
| trick is to get everyone on board in the project to do that.
|
| For public libraries I maintain, it's squash merges all the
| way. I like a clean history and the ability to check out that
| commit, compile, test, and run cleanly is perfect.
| giancarlostoro wrote:
| > If I see a ton of commits like "fixing formatting" or
| "oops", I want those squashed away into proper commits.
|
| Every team I'm in I strongly advise against such commits
| honestly. They don't help anyone, I emphasize being able to
| find things you changed if you need to find them. You can
| even enforce a format for commits.
|
| Funnily enough, I saw a wave of "fixes bug" "now really
| fixes bug" that got auto rejected by some commitcop utility
| at a former job, the guy was freaking out cause it wouldnt
| take all his changes. I guess they wanted to force him to
| stop doing such awful commit messages.
|
| Commit messages should be useful and historically
| descriptive.
| warmwaffles wrote:
| > Every team I'm in I strongly advise against such
| commits honestly. They don't help anyone, I emphasize
| being able to find things you changed if you need to find
| them. You can even enforce a format for commits.
|
| Same with me, but people still ignore it.
| [deleted]
| stinos wrote:
| In my opinion, yes, but like everything else it's not a hard
| rule. But especially for refactoring I really really want to
| read a comprehensive story of granular enough (but not too
| much) commits which logically follow each other, instead of a
| code dump with commit message 'bugfix'. That, plus just looking
| at the default graphical representation most git tools out
| there produce for merges vs simple rebased history: yes I'll
| take the latter.
| Nagyman wrote:
| As always, it depends. Especially for large PRs, I will go
| through the effort of rebasing to help the code reviewer so
| they can view key commits rather than a mile long scroll-fest
| on the GH "Files Changed" tab. It's about being a good co-
| worker and facilitating faster reviews.
| blktiger wrote:
| I sometimes prefer a rebase to a merge when pulling in changes
| from some other branch. It can be easier to deal with several
| smaller merges than one big one which a rebase accomplishes.
| This is not always true of course, so I usually start with a
| regular merge and if it's sufficiently complex or hard to
| untangle then I give a rebase a try to see if things get
| easier.
| sidlls wrote:
| Git is in general a terrible tool: I've always thought of it as a
| shining example of where "worse is better" ought to have been
| applied. Rebasing is one of its worst features. For non-trivial
| changes, anyway, it is often just a way to add complexity and
| messiness to what should be a simple workflow. And the benefits
| aren't at all as clear as its advocates contend.
| mixmastamyk wrote:
| Yes, and these folks are never around when you try rebase and
| get a forty file conflict and have no idea how to get out.
| Happened to me several times when I fell for one of these
| articles.
|
| You know what works almost every single time? With tiny
| conflicts if any? Merge + squash on gitlab.
| Extigy wrote:
| If a rebase goes wrong and you want out you can run,
| git rebase --abort
|
| to return to where you were beforehand.
|
| I find that git is actually very good at explaining what is
| going on and what you should do next by just running git
| status in the middle of some process like rebasing and
| reading what it says.
|
| Even if it all goes _really_ wrong the git reflog has always
| saved me.
| jbergknoff wrote:
| If I've already reviewed a PR and the author makes further
| changes, I definitely prefer to review an add-on commit. If the
| history is rewritten/rebased, then IME the entire PR needs to be
| re-reviewed from scratch. If we're talking about a <10 line
| change, then, by all means, rebase to your heart's content. With
| anything more complicated than that, rebasing a branch that's
| already been looked at can be disruptive and I'd strongly
| recommend against it (though squash-and-merge after review is
| fantastic).
| Shatnerz wrote:
| I didn't actually read the linked article but I see it is from
| GitLab. GitLab makes it easy to view the diff between versions
| of an MR even if it includes rebases.
| matijs wrote:
| GitHub does the same. There is a compare button that appears
| after a force (with-lease) push of a rebased branch.
| johnnypangs wrote:
| How does that feature work in Gitlab? I also use it along
| with a rebase policy at work and sometimes have that issue.
| nemetroid wrote:
| https://docs.gitlab.com/ee/user/project/merge_requests/vers
| i...
| jasonlotito wrote:
| Are there CR tools that don't display the diffs between
| rebases? Seems like a tooling issue more than anything.
| kotborealis wrote:
| Some code review systems, like gerrit, actually encourage this
| workflow: you can easily view diffs between commit versions
| ('patchsets').
| rubyist5eva wrote:
| In your view if a PR is not rebased but trunk is merged into
| it, does that warrant a full re-review? The end result is
| functionally the same as a rebase.
| thibran wrote:
| Changes should be added with additional commits. When the
| review is complet, the code should be rebased and merged (git
| merge --ff-only my-reviewed-banch). This leads to a clean git
| commit history and an easy review process.
| seba_dos1 wrote:
| > then IME the entire PR needs to be re-reviewed from scratch
|
| Why? What's the difference? You can still diff the previous
| version of the PR with the current version and end up with the
| same thing that an add-on commit would give you, but ready to
| merge as-is.
| Arch-TK wrote:
| Does your project have a policy of compiling and running (and
| e.g. tests passing) at EVERY commit?
|
| I can't imagine being able to easily enforce that without
| asking people to edit the correct part of their commit. It's
| maybe more difficult with gitlab/github interfaces where
| changing the middle of a sequence of commits will not render
| very well, but in email based workflows it works fine.
|
| On the other hand, being able to bisect a project without
| having to worry about whether an unrelated issue is causing you
| to traverse the wrong branch of the bisect is an enormous
| advantage compared to the minimal effort required of keeping
| track of a modified (rebased) commit in the middle of a set of
| commits under review.
| Supermancho wrote:
| > I can't imagine being able to easily enforce that without
| asking people to edit the correct part of their commit.
|
| I imagine something something githooks. However it might be
| enforced, it seems like a miserable way to develop.
| rjmunro wrote:
| You can now use --first-parent when you bisect to ensure
| bisect doesn't go into branches but stays on the main branch.
|
| https://git-scm.com/docs/git-bisect#Documentation/git-
| bisect...
| Arch-TK wrote:
| I don't see how this solves the problem of patches which
| fix up previous patches. This workflow doesn't require
| using merges, but it will introduce situations
| (irrespective of whether you use --first-parent or not)
| where patches fix previous patches potentially leaving a
| gap where code doesn't compile, doesn't run, or doesn't
| pass tests.
| chris_wot wrote:
| The one thing I'd like to do is to insert a commit between two
| commits, then edit this and then make a modification.
|
| Currently I create a text file, add this, then move this up to
| where I need to insert it and edit this commit.
| alisonatwork wrote:
| You can also just `git rebase -i` and set `e` (edit) on the
| commit before the one where you want to insert a new commit.
| Instead of doing `git add .` and `git rebase --continue` like
| you normally would to squash your changes into the commit
| you've stopped to edit, you can just `git add .`, `git commit
| -mwhatever` and then `git rebase --continue`. Now you have new
| commit "whatever" in between the one you stopped to edit on and
| the next one.
| throwaway_au_1 wrote:
| It's not clear to me exactly what you mean. Based on adding the
| text file, which sounds like you're creating a placeholder
| commit, you might not know about 'git commit --allow-empty'
| which may serve you better.
|
| Not exactly sure of your order of events wrt inserting a commit
| and editing it (I.e. edit commit message? Or changes?) and
| modifying it (I.e. see previous) but am happy to try and help
| if you want to flesh out your example a little more.
| throwaway_au_1 wrote:
| To speculate, maybe you haven't heard of fixup/squash.
|
| E.g. Commit 1 Commit 2 Commit 3
|
| Using an empty fixup commit, e.g.
|
| git commit --allow-empty --fixup=commit2hash
|
| You would end up with
|
| Commit 1 Commit 2 Commit 3 fixup! Commit 2
|
| Which will adjust automatically (when starting interactive
| rebase with autosquash) to
|
| Commit 1 Commit 2 fixup! Commit 2 Commit 3
|
| You could then simply change the rebase 'fixup' instruction
| to 'reword' to edit/remove the 'fixup!' part of the message,
| or 'edit' to continue the rebase uo until that commit and
| then stop.
|
| That said, again, not clear on your use case but maybe that
| might help you or another reader.
| mattpallissard wrote:
| Keeping your commits as separate units of change, and leveraging
| rebase/ff-only is worth is simply so you can do stuff like the
| following. git revert $(git rev-list
| COMMIT43^..COMMIT123 -- path/to/thing)
|
| I've been on teams where everyone _hates_ what a stickler I am
| about good VCS hygiene until they realize something that looks
| like it's going to be a big pain in the ass at first glance is
| doable with a one liner.
| mixmastamyk wrote:
| What is this a solution to?
| mattpallissard wrote:
| Reverting a range of changes for a given path.
| vincentkriek wrote:
| I sometimes run into rebases where solving merge conflicts 3
| times is hard. Replaying 3 commits for instance, where merge
| conflicts are present in each one. In the first I need to fix the
| merge conflict but remind myself that there are more commits
| following this that change this behavior.
|
| With a merge commit I am fixing the resulting work on both
| branches, which is easier than merging the in progress state in
| the current branch.
| abeyer wrote:
| Isn't that exactly what rerere is for?
| tcoff91 wrote:
| In these scenarios, I think it's better to use merge commits.
|
| Anytime resolving conflicts becomes pretty intense, where
| you're feeling like there's a significant risk of introducing a
| bug in the resolution process, I think it's better to use merge
| commits because then it's preserved in the merge commit how the
| merge conflict was resolved. If things were done incorrectly,
| you can trace it back to the merge commit and analyze it and
| you don't potentially lose important intermediate state that
| you might need to recover.
|
| On the other hand, If you're touching the same code in 3
| separate commits, then perhaps they shouldn't be separate
| commits. In these instances, I often do 2 rebases: 1 to squash
| the commits without reparenting them, and then another to
| reparent the squashed commit onto the upstream branch.
|
| Also, if you use merge commits for merging PRs, it's easy to
| cut through the noise of the commit graph by using git log's
| --first-parent option. Once you are using this, it's a lot less
| important to keep an ultra-tidy commit graph.
| divbzero wrote:
| The following tip from OP could be rather useful.
| git rebase --exec 'make test' main
|
| _The_ --exec <command> _flag allows you to run any shell command
| after each rebased commit, stopping if the shell command fails
| (which is signaled by a non zero exit code)_.
| OJFord wrote:
| I don't know if it's possible to write an article like this and
| not just be preaching to the choir; ignored by the flock that's
| already decided it doesn't like it.
| [deleted]
| chris_wot wrote:
| So what? If the crowd doesn't want to use it, what of it? You
| only rebase on your own changes before you push the patches.
| OJFord wrote:
| Well my suggestion really was just that it's pointless to
| write about, because you won't convert anyone. (Not '..and
| you should be doing xyz because that will convert them and
| that's what we want'.)
|
| But to answer your actual question, there are various ways in
| which what others on a team do affects you:
|
| - CI building 'merge branch master' all the time _on master_
| , because of merge-pulling upstream changes after committing
|
| - spaghetti merge feature branches (that you might be
| reviewing, working jointly on, or as below)
|
| - git log, blame, etc.
| holoduke wrote:
| Rebasing is merging multiple commits to one commit right?
| Basically you commit your small changes to your local master
| branch and at some point you merge them to one commit and push
| them to master repo?
| dnsmichi wrote:
| GitLab team member here.
|
| You can use `git rebase` to perform the so-called "squash"
| action, that squashes multiple commits at once.
|
| For example, the latest commits in the branch look like this:
|
| 123 WIP1
|
| 456 WIP2
|
| 789 WIP3
|
| 012 FeatureA
|
| WIP1,2,3 as commits should be merged into a single Git commit,
| and be put on top of the FeatureA commit - so to speak, use the
| FeatureA commit as a new base.
|
| Git uses the rebase command to do exactly that - you'll perform
| an interactive rebase onto FeatureA commit. The interactive
| rebase allows you to define specific actions.
|
| "pick" keeps the commit. In order to perform a squash of the
| WIP1,2,3 commits, you'll keep the first WIP1 commit, and tell
| Git to continuously squash the next commits WIP2 and WIP3. Each
| operation is done at once.
|
| pick 123 WIP1
|
| squash 456 WIP2
|
| squash 789 WIP3
|
| pick 012 FeatureA
|
| This results in a new history and commit - squashing changes
| the commit sha checksum, with new content in the Git commit, as
| well as a new base commit.
|
| 567 Squashed
|
| 012 FeatureA
|
| "squash" in an interactive rebase keeps the individual commit
| messages for each commit, and at the end, the editor for
| commits allows you to edit the final messages. This can be
| helpful to review the squash action, and for example amend or
| abort it.
|
| If you plan to not keep the individual commit messages, "fixup"
| throws them away and can be used as alternative action.
|
| "git rebase -i" has more options - you can also stop at a
| specific commit, and amend it, e.g. when a "git add" was
| missing a file earlier.
|
| Note: Any change to a commit within the Git history forces all
| later commits to change too, as the linked commit base changes
| too, thus regenerating the sha checksum. This entirely rewrites
| Git history trees, and can be very invasive - if you intend to
| keep specific commit IDs (for release tags for example), ensure
| that the workflows to not allow rebasing on certain branches.
| One possible workflow is to keep the main default branch
| protected, disallowing to rebase and push a changed history,
| add git tags there, and only rebase in a Merge Requests branch
| prior to review/approve/merge cycles.
|
| Moving from Git commands to GitLab - GitLab also offers a Merge
| Request option to squash commits automatically when the MR is
| accepted, so that all commits in the MR branch are squashed,
| and you don't need to do it manually.
| https://docs.gitlab.com/ee/user/project/merge_requests/squas...
|
| Last but not least - the quick action /rebase in a MR comment
| allows to trigger a rebase via the UI too, thus not requiring
| client side clone/fetch/rebase. More tips in
| https://about.gitlab.com/blog/2021/02/18/improve-your-gitlab...
| hkdobrev wrote:
| That's squashing which could be achieved with rebasing, but
| rebasing is larger than that which allows you to order and edit
| your history.
| shagie wrote:
| Rebasing is re-applying a sequence of commits to a different
| parent.
|
| I like using explain git with D3 to show how things work -
| https://onlywei.github.io/explain-git-with-d3/#rebase
|
| Compare that with merge - https://onlywei.github.io/explain-
| git-with-d3/#merge
|
| At the end, the HEAD has the same content, but the structure of
| the graph is different.
|
| Note that rebase falls in the set of "rewriting history"
| operations in git and so pay attention to the caveat in the
| explanation:
|
| > For this reason, you never want to rebase commits that have
| already been shared with the team you are working with.
|
| Rebase and reset are two of the commands that need to be done
| with caution and full awareness if working with commits that
| have been shared with other people.
| Tade0 wrote:
| No rebase tutorial is complete without the --onto option, which
| lets you essentially transplant a series of commits to a
| completely different branch.
|
| Very useful when you've created a branch(A) based on another
| branch(B), which in turn was based on master, but in the meantime
| master had a few commits added, so while it's trivial to rebase B
| with master, rebasing A with an updated B won't work.
| b3morales wrote:
| The latest git release has an option to handle this multiple
| branch scenario for you: `git rebase --update-refs` I don't
| know why I can't find any announcement of this other than a
| GitHub blog, but here it is:
| https://github.blog/2022-10-03-highlights-from-git-2-38/
| perryizgr8 wrote:
| Rules I would have everyone follow if I was a dictator:
|
| 1. 1 PR, 1 commit.
|
| 2. 1 PR cannot have more than 50 lines of product code added. Any
| number of lines can be removed. You can have up to 100 lines of
| test code.
|
| 3. Every PR should include a set of tests for the added/changed
| functionality. They must pass.
|
| 4. Git merge is forbidden. Everyone must rebase.
|
| 5. Every PR goes into master. Nobody can push to master. You can
| create as many feature branches you like, but definition of done
| is that your code is available on master.
|
| 6. Identify relevant existing test cases and make sure they are
| passing.
|
| 7. Master must always be in a state that it can be deployed
| instantly.
| lamontcg wrote:
| > 1 PR cannot have more than 50 lines of product code added.
| Any number of lines can be removed. You can have up to 100
| lines of test code.
|
| Hard disagree.
|
| Landing a single class/module to implement new functionality
| may take more than 50 line of code and 100 lines of test, even
| though conceptually the additional functionality is simple and
| it amounts to mostly boilerplate and looks like every other
| class that implements the pattern.
|
| Some large plumbing refactorings or CI refactorings are
| difficult to do in small chunks. I'm perfectly fine with a PR
| that replaces one internal API with another one and then has
| hundreds of small copypasta fixes littered around the codebase
| to swap out the APIs. Anyone should be able to read that
| without cognitive overload.
|
| Tests are also commonly over 100 lines of code since they tend
| to be repetitive by nature, and I'd like to not see those
| artificially broken up into smaller PRs since the most
| important question I've usually got is if all the cases are
| covered or not. Breaking 300 lines of tests up into 3 different
| PRs to satisfy some kind of line-length metric means now the
| most important question I have needs looking at all 3
| simultaneously and that is deeply counterproductive and totally
| useless. And small code changes with lots of comprehensive
| tests which fill out cross products of different API usages are
| great and should be encouraged.
|
| And while I don't personally like the dozens-of-tiny-atomic-
| commits approach, I deeply don't care if other people do it or
| not. I've never found it useful to read their PRs, or even
| after the fact, but I won't stand in the way of them doing that
| if it is what gives them enjoyment (OTOH, I never do that).
| AtlasBarfed wrote:
| Maybe a good rule for projects in maintenance mode. Large
| scale refactors? Well, that's impossible under these rules,
| well unless you go full LISP on what a line does.
| lamontcg wrote:
| Mostly what I've done is maintenance mode, that's where if
| you try to touch something it is often very complicated in
| secondary effects and fixes, and requires lots of tests.
| And additions of functionality which are bolt-on will come
| with 10 years of accumulated requirements around the shape
| of any new code and the tests.
| itslennysfault wrote:
| A lot of people have hate for rebase, but I've always LOVED it.
| I've always had way less issues with it than merge. Whenever I do
| a feature I work in a feature branch then just rebase it with the
| target branch (main) before submitting the PR and it is a really
| painless workflow I've used for years.
| rmetzler wrote:
| I really try to like git rebase, especially git rebase -i and
| at one time I even used a special tool to help with that. What
| I find is that I see a lot more merge conflicts than in Gitlab
| MRs, but it could also be that the tooling on my machine is
| suboptimal: switching between VSCode as the editor and using
| vim in a separate terminal for git. In vim I don't see the
| current commit where the conflicts appear.
| hoten wrote:
| What was your tool? Was it more than the --fixup/--autosquash
| feature (perhaps your tool predated that)?
| BeFlatXIII wrote:
| I made some minor contributions to MuseScore a few years ago
| and they turned me on to the joy of rebasing.
| ludwigvan wrote:
| On Mac, I prefer Gitup, a free and open source GUI which makes
| rebases (and a bunch of other git operations) much easier:
| https://github.com/git-up/GitUp
| DBCerigo wrote:
| A much more in-depth, advanced, and more valuable imo, article on
| the same topic https://medium.com/@porteneuve/getting-solid-at-
| git-rebase-v...
| kartoshechka wrote:
| irony is that my team use gitlab and we have auto squash before
| merge, avoiding manual rebasing
| xyzzy4747 wrote:
| I would recommend not doing anything complicated such as git
| rebase and just add more commits, patches (git diff / apply), or
| merges until your code works. If the number of commits is large,
| it doesn't really matter. Optimizing for a pretty looking git
| history is probably the most foolish thing to focus on.
|
| If you are doing anything that involves rewriting the history you
| are doing it wrong.
| Nagyman wrote:
| > Optimizing for a pretty looking git history is probably the
| most foolish thing to focus on
|
| It's not about "pretty"; commits are a form of _communication_.
| Do we send emails without editing before hitting send? It's a
| means to optimize for easier reviews through better
| comprehension of the changes, which also leads to faster
| reviews. Our colleagues don't want to read a bunch of
| intermediate commits.
|
| > If you are doing anything that involves rewriting the history
| you are doing it wrong.
|
| Care to elaborate? What's your general strategy?
| chriswarbo wrote:
| > It's not about "pretty"; commits are a form of
| _communication_. Do we send emails without editing before
| hitting send?
|
| Writing clear, atomic commits is a good idea regardless of
| whether you use rebase or not.
|
| In your email analogy, rebasing would be altering previous
| messages in the chain. That doesn't make rebasing look good!
|
| > > If you are doing anything that involves rewriting the
| history you are doing it wrong.
|
| > Care to elaborate? What's your general strategy?
|
| Not the parent, but to me the most important part of VCS
| history is _accuracy_. Rebasing commits (or cherry-picking
| them) changes their context; that context can be important
| for understanding why things were done in a certain way. For
| example, imagine we 're digging through the following
| history, to understand how some feature 'bar' works:
| * Add workaround for Error(foo) in feature bar |
| * Implement feature bar | * Bump dependency baz
| to eliminate Error(foo)
|
| Why was a workaround for Error(foo) added, if that error had
| already been eliminated? Did that dependency change not work?
| Is there some more permanent way to eliminate Error(foo)? Is
| the workaround still needed?
|
| Compare that to the following, more accurate history:
| * Merge |\ | * Add workaround for Error(foo) in
| feature bar | | | * Implement feature bar *
| | Bump dependency baz to eliminate Error(foo) | /
| |/
|
| Here it's much clearer what's going on: the dependency change
| was not in place when that workaround was added. Hence the
| workaround shouldn't be needed anymore. Rebasing the 'feature
| bar' changes on to the 'dependency baz' changes throws away
| that information.
| k_ wrote:
| Good luck bisecting such a repository, unless you squash PRs
| (for which build passes of course)
| WorldMaker wrote:
| git bisect --first-parent bisects only the straight line of
| first parents of merge commits. If you --no-ff PRs and always
| have merge commits, it is essentially a bisect at the PR
| level without any need to squash the graph.
| bob1029 wrote:
| Rebase is something that I see a lot of developers shy away from
| but it is usually the right way to get a feature branch re-
| aligned.
|
| My practice is to rebase all my pending PRs each morning to make
| sure that the prior day's activity is coalesced.
|
| If you wait weeks and weeks to do the first rebase for a big
| change set, you can wind up visiting the same files and conflicts
| _way_ more times than is logical. In my experience, this results
| in a much greater chance of screwing something up along the way,
| further reinforcing for some developers that the rebase is bad.
|
| _Timely_ rebase is the answer.
| hoten wrote:
| --fixup has been incredibly useful for my rebase workflows.
| manbash wrote:
| Anyone who has experienced rebasing a PR on github knows how much
| it hurts the review process.
___________________________________________________________________
(page generated 2022-10-06 23:02 UTC)