Rebase and merge pull requests
github.com
github.com
The trees in the rebased commits are new and may never have been tested. Is GitHub going to expose a `refs/pulls/123/rebase` ref (cf. the existing `refs/pulls/123/merge`) for running through CI before the button can be pressed?
EDIT: The docs [2] say:
You aren't able to automatically rebase and merge on GitHub when:
* Your pull request has merge conflicts.
* Rebasing the commits from the base branch into the head branch
runs into conflicts.
* Rebasing your commits is considered "unsafe", such as when a
rebase is possible without merge conflicts but would produce a
different result than a merge would.
So I guess the point is moot. You can’t rebase a branch unless the resulting tree is identical to the one you’d get from a merge, and that’s the tree that runs through CI.[1] https://twitter.com/ChrisGSeaton/status/780441251992731648
[2] https://help.github.com/articles/about-pull-request-merges/#...
Basically it adds the commits to the master branch without a merge commit:
e.g.:
master: A - B - C
feature: D - E
master (after merge): A - B - C - D - E
See: https://help.github.com/articles/about-pull-request-merges master: A - B - C
feature: D - E
post-master: A - B - C --------- F
\- D - E -/
So in the view of the master the entire branch is one clean commit, but the branch history is still preserved.I have a `git log0` alias for this, as well as `git blame0` and `git show0`.
Yes, however that only works in the CLI, not in any Git GUI I know of (though GTK Bazaar log would pretty much do that, folding merge commits & following the mainline by default).
It's nice to see the later finally getting some love so I don't have to keep going back to my own terminal after my PR is approved.
Why would you have to go back to your terminal after the PR is approved? In either case, the merges are done by the admin..
In short: all devs are admins.
edit: anyway this would still be a huge help to the sole admin if we had one.
Isn't the usual standard "rebase && merge --no-ff?" Yielding a merge commit but lower branch interleaving in the logs? This is going to dump all the branch's commit into the mainline.
What does "keeping authorship information intact" mean? It says it resets the committer - when I'm going through `git log` or `git blame` output, doesn't this mean that I won't actually see the correct author? I don't want to have to dig through commit messages to get an accurate understanding of who wrote what.
https://gitlab.com/gitlab-org/gitlab-ee/issues/150 https://gitlab.com/gitlab-org/gitlab-ce/issues/4106
So does merging.
> or that conflicts have been fixed in the branch prior to the merge
Conflicts that show up in rebasing may not necessarily show up during a merge. Having to fix a bunch of conflicts that only occur because you rebased is tedious and introduces a source of potential error.
Surely there must be a way to tell git to show history in that form even with branches that haven't been rebased?
From an aesthetic perspective, rebasing and ff merging also destroys the history of what commit is related to what work branch.
The merge commit acts as a kind of "pushlog"; it tells you what actually landed together as a single unit. It probably also tells you what passed CI; although many projects state that you shouldn't have individual commits that don't pass CI it's rare that this is enforced below the level of the PR. That should be good for bisection. Because the commits are always rebased onto master (and of course you never allow merge commits other than from code being integrated into master) your history is relatively clean, you don't get multiple overlapping branches, but something like
M1 ------- M2 -------- M3
\ B1 - B2 / \ C1 - C2 /
Because the merges are --ff-only you don't get the confusing situation where the merge commits themselves contain changes.In principle this seems like the ideal way to use the tools git provides. However I understand there are some minor rough edges e.g. with magic needed to tell git bisect how to only try the merge commits.
Then was convinced even more after having to revert a ff merge.
Right, but what's the benefit of that? You still need to understand a history with merges in, in which case it seems like you might as well get the safety advantages of not rebasing.
Github also has protection to prevent branches from being forced, if you are only forcing a feature branch with no collaborators, or at the end of collaboration, it's not so bad, especially when git tells you the old hash you just overwrote and you have the reflog, but again github's rebase-then-merge should make that a non issue.
People are bizarrely terrified of merge commits.
Isn't that essentially what this is? It's a rebase followed by a fast-forwarded merge, there should be no merge commit.
I'm amazed at how many companies allow branches rather than allowing repo forks.
If you have a normal merge based workflow, your bisect will likely require some babysitting because git doesn't offer an easy way to just bisect your merge commits into master. Firstly of course there will also be many more commits to consider, most of which you don't really care about at this point and which will slow down the bisect. More importantly some of the intermediate commits from the feature branches will almost certainly be broken, because typically not every single commit even goes through CI. You can work around that by hacking something up to ignore these commits but it's probably gonna be a pain.
Once you found the problematic feature you want to back out you then will spend half an hour googling how to revert merge commits.
Of course, there are advantages to having the "intermediate" commits available and if git bisect were better designed the experience with merge branches should be strictly better, but in practice it's enough of a pain that people who semantically prefer merges opt for a rebase-based workflow.
git bisect skip. Also, if your maintainers aren't doing a `git rebase -x "make test" origin/master` before merging then you're the ones to blame. Not merge commits.
> Once you found the problematic feature you want to back out you then will spend half an hour googling how to revert merge commits.
`git revert <merge commit>`. Or if by "revert" you mean "change the history to the state it used to be in" you can do `git reset --hard <old HEAD using git log --first-parent>`.
> Of course, there are advantages to having the "intermediate" commits available and if git bisect were better designed the experience with merge branches should be strictly better, but in practice it's enough of a pain that people who semantically prefer merges opt for a rebase-based workflow.
git bisect is actually quite well designed considering it works given any two commits (even if the histories are different). To be fair, it doesn't handle histories where a bug is fixed and broken multiple times -- but there's no nice way of dealing with that (it's a hard problem to solve without iterating through each commit).
Don't build a series of commits where a later one fixes an earlier one; organize them into a logical series of changes, such that the project works after each commit.
Right now build systems don't even do the "build and test the final commit" bit right; it should of course test against a pre-merge (not on the branch) but again that tends to be a pain to set up.
https://github.com/jleclanche/fireplace/commits/master
Versus a merge tree:
https://github.com/hashicorp/terraform/commits/master
Consider that the git log is one of the first thing contributors will look at. The cleaner it is, the better the experience.
I've been waiting for this for a long time. Thank you github!
Point is, it's good to have both. And personally, I find terraform's git log unreadable and unusable.
Now we could use some UI improvements to the github commits page to make the merge method not look so ugly. Lets say: collapse merge commits into a single gray line and roll up the commits made on the branch(es) underneath the merge commit line, maybe indented.
In terms of the preservation of useful information, I vastly prefer the merge tree. And using merge trees appropriately and never using merge trees at all are both matters of discipline.
Whether it's faster to search for something in a flat tree or not remained to be proven. It feels like it's mostly a matter of personal taste.
Edit: And for fucks sake can't I be happy GitHub implemented an outstanding feature request I've personally been asking for years? The cynicism from some of the people on this site really gets to me sometimes. Stop.
The problem is that this merge option is considered by many to be actively harmful, and GitHub adding support for this is basically them tacitly saying that this is a perfectly fine merge method to use. This will almost certainly cause an increase in the number of people using this merge method, which is a shame as it really should be discouraged instead of encouraged.
The other problem is the main argument in favor of this merge method is the fact that GitHub displays non-linear commit histories terribly. That should not be an argument in favor of having a poor merging strategy, that should be an argument in favor of GitHub revamping their commit history display to actually be useful.
It is not up to you to decide other people's and teams' workflows. It is not up to you to decide what is or isn't harmful in the context of another team. And it is certainly not up to you to decide that GitHub shouldn't provide features their paying customers are asking for, because of concerns of a completely different context and workflow.
I appreciate that you are more than familiar with git, but that doesn't give you free reign to decide what is and isn't an antipattern for other people. In fact, you should understand far better than the average HN user just how absurd your reasoning is if you'd step back from it a little.
What you call antipattern, a lot of people call feature. If GitHub now clashes with you on a philosophical level, consider moving to GitLab (oh, wait, GL has supported this and far worse for a far longer time).
The developers using rebase flows do not affect your life. They do not affect your work. They, and their "antipatterns", are as harmful to you as an iOS user is to an Android one. And your merge flow does not affect me. What does affect me is reading constant unwarranted negativity on Hacker News, a community where my expectations have so far been above those of reddit's unending stream of cynicism. And it bugs me far, far more that this has been your reaction to a company listening to its customer base, than you or I could ever care about deciding what flow is or isn't an antipattern.
Bloody hell.
> The developers using rebase flows do not affect your life.
Yes they do. If they didn't affect my life, I wouldn't care. But every time I have to deal with an open-source project that adopts this workflow, it affects me. Every time I end up working on a project that's adopted this workflow, it affects me. And it affects me in more subtle ways too, such as tooling being geared around a largely-linear history instead of a history with lots of merges (e.g. GitHub's commit history display).
> And it bugs me far, far more that this has been your reaction to a company listening to its customer base
They're barely listening. There's a long list of far more valuable changes they could make, that they're not doing, because they seem to not really care. It took an extremely long time, a very high-profile blog post calling them out, and competition from GitLab for them to finally start improving the core of their product (pull requests), and they're still missing a lot of useful functionality (e.g. rebase tracking). And of course they haven't even touched the commit history display, even though, as has been mentioned multiple times, it really sucks for a non-linear history. In fact, most of their product hasn't improved in a long time.
I don't understand this. The commits are rewritten - do they overwrite the author to the current user, or don't they? Or is there a distinction between "author" and "committer" I'm not aware of? Which one does blame use?
Difference between author and committer in Git? -- http://stackoverflow.com/questions/11856983/why-git-authorda...
Why git AuthorDate is different from CommitDate? -- http://stackoverflow.com/questions/11856983/why-git-authorda...
What does “authored 7 days ago; committed 14 hours ago” mean on GitHub? -- http://webapps.stackexchange.com/questions/70383/what-does-a...
I found all of that by googling "author vs committer git".
The gist is that, yes, there is a distinction. If your friend, say, gives you a diff and you apply it with `git apply`, you're the committer and your friend is the author.
EDIT:
Regarding your other questions ("Which one does blame use?"):
If you run
$ man git-blame
This is right at the top: NAME
git-blame - Show what revision and author last modified each line of a fileA rebase rewrites history, as if the PR had been written on master directly. There is no merge commit and no evidence of a previous branch. Some people prefer rebasing over merging because it gives you a linear commit history.
`git-rebase` will rewrite the history of the current branch. In this case, github will rewrite the history of the branch that you would like to merge such that the base commit (hence the name "rebase") or the commit that was branched off of is the latest commit on the default branch (usually master)
Then when you merge it, you'll get a merge commit or not depending on whether or not you do a fast-forward merge
For example,
- Force SSL flag when connecting to server
- Use new syntax for SSL flag
- Wrap flag implementation to its own method
- Add forgotten tests
This branch's main goal was to use ssl flag on external requests but ended up having several commits that does not really matter to other developers. Then you want to squash this branch into a commit and merge.
Rebase and merge example,
- Improve sorting by adding cache
- Implement a separate config class to fetch caching times.
- Modify search implementation to use cache config class
These are rather important commits by themselves and better keep them separated in your history.
Which you could already do with a regular merge. Just because the commits are fine as part of a branch doesn't mean you want to keep them as part of mainline.
Can you elaborate on this? I would be happy to learn more about it.
What masklinn means is that when you just merge a PR, the history is retained as-is (same as with rebase). But instead of the history being flat, it's bumpy.
I'm not missing any point, I'm saying you already get that benefit with the original merge strategy.