Git Reflow
github.com
github.com
When I think I'm done with a feature is exactly the time that metadata becomes relevant! Why would I want to lose it?
If anything, I wish ides would integrate git-blame more into my visualisation of a file
But there are so many people into it, that I feel I must be missing something obvious and it bothers me.
I wish git had a first-class model of a milestone-ish block of commits, so that the detailed commits and the feature milestones are disambiguated. I try to do this with merge points, but it doesn't seem to always work out, and since it's not native, it depends entirely on convention.
It's ok, I'd just like to be able to apply this structure to stuff like bisect or blame.
(p.s. your old comment on "git branching models" that starts "Not another one. All good git workflows are different..." was hilarious/awesome - https://news.ycombinator.com/item?id=11193048.)
> When it really comes down to it, the only place we care about enforcing a particular style of commit is in the master branch. We don't care if you make a thousand commits to get there, the only thing we care about is the individual features that come in from each (small) pull request.
> And while the history is nice, the biggest advantage of using the squash merge is that over time, git blame becomes way more useful. You get to see for every line of code in your project, not only the person who changed it, but their commit in the full context of why that change was made, including an easy-to-reference link to the pull request and ideally (through the pull request description), a link to the ticket tracker. So we can tie any line of code all the way back to the ticket that caused it's creation.
> And over time, that's all we really care about in the history. Who made this change and why was it made. Squash merging allows us to do that while still giving all of our developers the individual freedom to develop in the way that suits them best. To try and enforce commit styles in branches owned by other devs is to me, micromanagement that will go against the best results.
This is somewhat fair, but I feel it needs to be noted that even if you don't squash commit, if you look up a commit in Github, at the top of the page it will link you to the PR even if that commit is not the merge commit. I use this all the time to go from a random commit to a PR in our code, even though we do not squash commit. (We encourage, but do not enforce, an autosquash rebase against master; that is, history is kept, but you're permitted fixup! commits for really silly things like typos that we don't care to remain in the history, and it's left to your judgement what should be kept. The rebase cuts down on the amount of criss-crossing branches.) That said, I also use the individual commit message to, as the grandparent noted, figure out what a dev was — or wasn't — thinking.
Is there something about the Hg architecture that makes it easier to plug in something like Evolve than with Git? Evolve isn't enabled out of the box on Mercurial either.
The "only" thing the Evolve extension does is expose a UI for creating and manipulating obsolete commits, but it's not the only extension that does it.
So, I guess you could build Evolve for git, if you absolutely cannot be persuaded to use anything but git. You would need to build obsolescence markers, and the proper logic for exchanging them between clones. Getting this right has taken a lot of work for hg, but maybe now that the ideas are mostly there, it would be easy to replicate them.
As someone in favor of squashing, I can say that I don't want to see things like "oops, reverting last commit" popup in my git history, especially if I'm browsing history or bisecting a bug. That's noise - useless data. OTOH, commits should be the Minimum Necessary Change to accomplish a well-defined goal. The code itself should always be clear on what it is doing, otherwise it's badly written. If it's "deep magic", then comment it in the code as such.
That being said, I do think that reasoning for why a change was made, at every level, should be in the commit message. I'm also not a fan of merge, but prefer squash+rebase.
In all cases/workflows, it can be abused, and people writing bad code, bad comments or bad commit messages will do so until you can make them care to do it better. There's no silver bullet.
There's a middle ground between squashing and leaving a load of disorganised crap in the history. Rebase before merging. It gives you a chance to clean up the rubbish, but it doesn't force you to squash an entire feature's work into a single commit. You can preserve the logical changes without letting the crap into your history.
But as part of your point that commits should be the "minimum necessary change", it makes sense to send a logical series of patches that iteratively change a project to implement a new feature (e.g. adding new infrastructure), rather than one big patch to implement that feature.
Yes, but WHY it does that may not be obvious. "Oh, this code checks for a funny condition, but why would we care about that?". That's what commit messages are for.
That said, I still prefer squash/merge myself.
There's value in both use cases: 1. Scrolling through the log to see an overview of the direction of the project on the level of complete features. 2. Being able to see exactly when, who, and why any single specific line was changed.
Squashing gives you 1, but throws out 2 on the way.
I'm the complete opposite. When I do a blame I want to see a direct link to the feature. I couldn't care less about the specific commit that changed the line.
I personally like to create a new branch locally - sometimes I'm experimenting and get ahead of my commits, and then I'll make 3-4 commits in bite-sized concepts. Other times I'll commit something that seems like it will probably work, and then I realize it doesn't, so I'm able to revert/reset the commit (so the commit is deleted rather than seeing a commit and then a revert in the log). And once I'm close to done, I can even rebase so my clean commits are all in a row. Then I push my branch.
I lose all that flexibility as soon as a team's process demands I push my branch as soon as I create it. I can no longer rebase (I still don't understand the guides that explain how to use rebase after pushing), reverts add noises to the log, merges from master interrupt the flow, etc. So in that sense, I can see the allure of a squash-and-merge to master.
I just don't think that pushing an empty feature branch takes advantage of the benefits of using git.
You have protection on your remote trunk branches against force push.
You have git configured to push only the branch you are on, to the same name on the remote.
git rebase; git push -f;
It is HARD, DANGEROUS and SHITTY under other configurations.
<3 Git.
It'd be nice if git let you push (for backup/protection) without letting other people see it or check it out yet.
Another option you might consider, if you need more flexibility, is doing your work in a branch off of your `feature-branch`, e.g., `feature-branch-wip`. When you're happy with your progress on `feature-branch-wip`, interactively rebase atop `feature-branch`, merge in, and push. Their process is satisfied, and they'll never be the wiser.
And then if you're working on a larger feature, you have that feature branch and make these small one-commit merges into that branch. When you merge that larger feature - it'd be great not to squash those commits.
We have worked in environments that promote rebasing of feature branches, and while that may work well, it can lead to holes in the history of the review process due to the need to force-push.
That said, we are nearing a stabilized core API and have plans to allow for more flexibility in the process. If you are interested in following our ideas behind this, feel free to follow the issue we have open: https://github.com/reenhanced/gitreflow/issues/53
Something is deeply wrong with the ecosystem when people want to do things like this!
If your workflow looks like this:
- Create a feature branch
- Write great code
- Create a pull request against master
- Get 'lgtm' through a code review
- Squash merge to master
- *Delete the feature branch*
As far as I'm concerned, commits should be rebased and squashed into logical units on the feature branch before merge, that's the responsibility of the dev. Squashing them all into one monster commit feels like a terrible idea.If that information is valuable to you, great! This is why we have several ways to do things. The trend you're seeing simply seems to indicate (mildly indicate, at best) that a larger percentage of HN readers prefer to squash and merge.
Each to their own.
See how annoying that is? That's what it feels like to me to read non-squashed commits.
option A) SQUASH ALL THE THINGS option B) HISTORY IS SACRED AND HOLY
We just make sure that the developer rebases and squashes the meandering micro-commits into parent logical units before merging. This gives us both sensible logical commits, and avoids monster commits.
I spend enough time spelunking through history that I dread seeing something like this when I need to track down the context for a particular change
client/something.js | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
critical/something.rb | 41 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------
gulpfile.js | 7 +++++++
lib/stats.erl | 24 ++++++++++++------------
api/somethingelse.js | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
critical_api/another_thing.rb | 41 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------
webpack.js | 7 +++++--
lib/mapreduce.exs | 24 ++++++++++++------------
client/user.js | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
critical/security.rb | 41 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------But only people who are bad at git ever post things on the internet about git! (with the exception of Junio's blog)
If a typical feature starts with some cleanup/refactoring, I don't mind seeing that work separated from the new implementation in master. Some would consider a pure refactoring noise that shouldn't be in master.
There seems to be an argument too that unless you have a policy of squashing completely then the outcome will be noise and not enough squashing. That depends on the people of course.
That's what I thought but it's not quite "no one". There are some who'd love to have all git commit history, and if it was possible, the entire editor text buffer histories and keystroke logs of other programmers' work. This was my reply to it:
https://news.ycombinator.com/item?id=11408221
The post I replied to qualified it with "this may be a minority position" but his comment happens to be the topmost comment so lots of HN voters agreed with him.
Based on the repetition of this "git rebase" topic, I can only guess that roughly half of git users want to see all git commits with "oops, stupid typo", and the other half don't want to be inundated with meaningless noise. I really have no idea though.
Madness.
I did qualify my suggestion that no one wants "oops typo"-commits with "in any sane workflow" :)
As long as I can bisect, I don't much care about the details. But this is definitely not compatible with three dozen commits mostly consisting of "oops didn't compile" and "forgot comma" and "fix syntax erorr". You've gotta do something about that.
The way some people talk, the only acceptable history is an asciinema [1] recording of the development process with a microphone recording the developer's mutterings as it goes. The question isn't about what information you "lose" but about what you keep, because you must discard the vast bulk of it. We're arguing here about whether we chuck 99.97% or 99.99% of it.
Git allows you to clean up your feature branches to prevent these kind of fix commits.
Look at git.git. They don't require people to squash all their commits into a single patch, but still every patch should be compilable.
If I can't bisect, I don't approve. So, by simple logic based on the premise you supply, I also disapprove of large commits.
My point may not be what you expected prior to reading.
Note also that many other commits that could not build did not contain the bugs ;-)
(Speaking of luck, I worked with a codebase where the bug was always inside a jumbo commit involving at least a hundred of files)
$ git reflow setup
Please enter your GitHub username: nhance
Please enter your GitHub password (we do NOT store this):
Your GitHub account was successfully setup!
That implies that the username is actually stored somewhere. Is it stored locally or on some reenhanced.com server? The README should be very clear about what exactly gitreflow stores and where.git blame is already an approximation (because git, and well, everything, does not record what you did for real, only the smallest set of binary delta instructions you must execute to produce file version 2 from file version 1).
So this is essentially is "this one git command sucks, so we are going to destroy all of history to make it's output slightly better in a few cases", instead of "hey, we are going to produce a version of blame that identifies the kind of info we care about"
* open issues to address
* review state, such as "changes requested" or "approved" (along with users that are in each state).
We've been using Phabricator's[1] Differential tool for code reviews and it feels superior to this process, but it would certainly be nice to have an all-encompassing solution for this.
This project seems to be done much cleaner though and in a more abstract and reusable manner. Well done!