Hacker News new | ask | show | jobs
by nordsieck 1041 days ago
> It is my experience however, that either everyone needs to rebase or you end up with issues eventually when only some developers are and other ones aren't.

The only time I merge is when I'm working on a shared remote branch. I haven't found a workflow (although I'm all ears if you have any suggestions).

1 comments

Here's my current workflow:

1. write some code on a local branch

2. upstream has new revisions? rebase my branch on top

3. if not finished with my task yet, go to 1

4. if ready for review, open PR

5. if accepted, squash and merge

6. if changes are requested, write more code

7. upstream got more commits causing a conflict? don't rebase! it will screw up the PR history on GitHub and can cause issues for reviewers who might've checked out your branch locally and maybe done some experiments. merge upstream into your local branch. then you can push fast-forwardable commits.

8. push new commits to PR and go to 5

I used to think of rebasing as just rewriting commit history. But now I also think of it as altering the history of collaboration that is captured in a PR. So I switched from rebasing onto new upstream base branch commits and force pushing to PRs that already had reviews, to merging in new upstream base branch changes. I only do this after someone else has done anything on my PR; if I open it but nobody has reviewed yet, I'll do the rebase/forcepush to keep it current until someone does.

I prefer squashing to merge because I prefer the default branch to have one commit per unit of collaborative work. The way different people split up commits on a branch is arbitrary and varies widely; you'll never get more than 2 engineers to agree on a convention here. Keep all the messy stuff in the PR, and you can always revert one of those individual commits if you want finer-grained rollback. If you want a PR to have generated more than one commit, then it should be more than one PR.

> I only do this after someone else has done anything on my PR; if I open it but nobody has reviewed yet, I'll do the rebase/forcepush to keep it current until someone does.

I believe the only reason to do so is GitHub's lackluster PR UI. Force-pushing with an updated version of a branch after a review works reasonably well with GitLab's MRs.

> I prefer squashing to merge because I prefer the default branch to have one commit per unit of collaborative work.

There's no reason to squash when you can create merge commits from fast-forwardable state instead (again, one of the easily achievable options in GitLab's UI; GitHub doesn't make it easy AFAIK). This way you don't lose commit granularity while you can still obtain the "one commit per unit of work" view with simple `git log --first-parent` (or do the opposite and skip the merge commits with `git log --no-merges`).

> Force-pushing with an updated version of a branch after a review works reasonably well with GitLab's MRs.

The problem I run into is that other people have different workflows.

If they `git checkout remote/branch`, then everything's fine. But if they want to make a local copy of the branch, it'll get all messed up if I force-push. And I only want to adopt practices that are as robust as possible in the face of the possible ways other people could work.

For me, individual feature branches feel private, even if they’ve been pushed to a hub repository for others to view and pull. I wouldn’t push to someone else’s branch and I frequently force push to my own branch without worrying what it will do to others repositories.

The only thing that is sacred is the main/master branch. Everything is else just a speculative idea that, until reviewed and applied to master, is ephemeral.

(I’ve tried collaborating on a branch before but at the end of the process it’s hard to review because you either feel like the other party is rubber stamping their own code alongside yours, or you need to find a third party reviewer which spoils the 1:1 nature of almost every other code review I do.)

> (I’ve tried collaborating on a branch before but at the end of the process it’s hard to review because you either feel like the other party is rubber stamping their own code alongside yours, or you need to find a third party reviewer which spoils the 1:1 nature of almost every other code review I do.)

In my experience, that's part of the negative side of pair programming as well, although I really like it in general.

> There's no reason to squash when you can create merge commits from fast-forwardable state instead

Sure there is. Less noise commits.

Did you mean to say "less value in commit graph"?

It's literally just a matter of a single command line argument to switch between views of whole MRs and individual commits, and both those views can be incredibly useful (especially during bisection).

I still haven’t tried your suggestion, but would it be able to show only merge commits from PRs already merged into main, while still showing all commits on my local work branches I have in progress?
`git log --first-parent` shows you only the list of commits accessible from HEAD by traversing their first parents. So, yes - your local work will usually have commits with just a single parent, so nothing will get skipped until it gets to merge commits.

It's also useful to skip noise if you happen to merge the upstream branch back into your topic branch for some reason.

Also, there's always `git log main..`, or even `git log main..topicbranch`. Combined with `--oneline` and perhaps `--graph`, `git log` is a really powerful tool to visualize repository state (and something that's incredibly lobotomized on popular Web frontends, unfortunately - I often end up cloning a repo to browse its history just because the Web UI is useless).

What's an MR?
Merge Request - sometimes misnamed as Pull Request.
My workflow is almost identical to yours except step #2. Why rebase on main when you can just merge from main? It's much simpler, less likely to get hairy merge conflicts. If you're going to squash your PR anyway, the end result is identical.
I really don't get all these people who insist on usingrebase instead of merge. Who wants to spend time resolving meaningless conflicts?! Every time I try it, I instantly regret it.
> I really don't get all these people who insist on usingrebase instead of merge.

I prefer not to squash before committing. I like having smaller commits in my history.

And if you don't squash, then using merge to fix conflicts with main/master before merging looks a lot more confusing.

> Who wants to spend time resolving meaningless conflicts?! Every time I try it, I instantly regret it.

Typically it doesn't take a lot of time unless you do something weird. Although to be fair to you, it does take more time than using merge.

I like being able to see the graph with my commits lined up on top of the latest main revision. It helps me order my work in my head. There’s probably a bunch of other ways to visualize that, I just haven’t learned them yet.