Comment by falcolas
7 years ago
A git off my lawn moment: Every time I see someone complaining because they have to dive into the reflog to fix their own mistake, all I can hear is "I was operating my table saw without using a push stick and can't understand why I lost a thumb".
Friends don't let friends (especially those who don't learn how to use their tools) rewrite shared git history. If you don't understand rebase, amends, etc can do to your (and everyone else's) repo, DON'T DO IT.
On the other hand, doing it is the only way you're going to learn. Just do it in a safe environment, with a snapshot of the repository.
Yep. That is the important tip, right here.
Then relax. This is extremely important before playing with nasty Git surgical tools such as huge rebases. Borked it up?
Undo is a great thing, and it's also important to triple check the entire state of the repository before you push, because pushing is basically committing to whatever surgery you've done. If you're having to fix stuff with -f, you're going to run into trouble; try to avoid -f ever.
This is so wrong. :) With git you exactly do not have to backup your local workspace, because it already is backed up in git.
If it is committed, it is safe. You can go back to it. If you messed up your branch, just reset it to something that was good. No need to do manual backups.
8 replies →
>If you're having to fix stuff with -f, you're going to run into trouble; try to avoid -f ever.
I disagree. I don't have much experience using git with big teams, but at least for small team where a developer usually owns a feature branch, force pushing to the branch to take into account criticism on commits can be helpful. Of course, in that case, feature branches are considered non shared.
Git own "next" branch is actually force pushed to all the time, to remove patches which didn't make the cut for example.
3 replies →
practicing safe version control is better than abstinence
I see what you did there...
This is a place where Mercurial wins out. Hg has the concept of phases that makes it much harder to screw up rewriting history:
https://www.mercurial-scm.org/wiki/Phases
Replacing a table saw with a circular saw (bad analogies abound) doesn't remove the opportunities for losing appendages. Especially for those who don't learn how to use the tools put in front of them.
"It is impossible to make anything foolproof because fools are so ingenious."
Yes, Git is a sharper tool with fewer blade guards than other version control systems, including HG. That sharpness and relative lack of safety mechanisms, however, lets you do things you can't in other systems. The real problem is that folks use these tools without attempting to understand them and cargo-cult onto a workflow which leaves them open to screwing things up.
To continue the "git off my lawn" moment - I've had to use the reflog exactly zero times in the past few years, despite using rebase locally on a fairly frequent basis (and sadly remotely to fix other's bungles as well). This is only because I respect git for its sharp edges, and when it comes time to re-write history with rebase, I work carefully.
Reminds me of a time I saw a funny Makefile mistake. SRCS contained both .cpp and .c files, and someone copied a recipe that only replaced .c ones.
Then they used the resulting variable in 'make clean'. That was more of an, 'oh shit, git pull' sort of thing though.
I use the reflog all the time to fix my own rebase mistakes; it's just on rebasing I've done locally, and where the results haven't made it out to a shared repo.
Rewriting shared history fits the metaphor pretty well.
But you can still chop off your thumb in your local history, and that's safe to fix - you just have to know where the duct tape is.
rebase can be dangerous, but so productive. I think it's important to teach new devs how to properly use it. Especially if you're working in a continuous deployment environment, where you may need to quickly revert something.
Reverting something does not require a rebase. It requires an aptly named command "git revert". Additionally, in the event that a deployed feature needs to be reverted, any halfway decent change management policy will want a history of what you reverted and why; a git revert commit can show both very cleanly.
And, frankly, since all rebase does is re-write history, I fail to see how it's inherently productive, especially in the context of re-writing the history of previously shared commits. Yes, it is capable of cleaning up and reducing the number of commits you have to read through when looking at history, but that's such a rare event that optimizing for it (especially by normalizing dangerous commands like `git push -f`) seems, well, premature.
Completely agree. Rebase is practically only safe on single developer feature branches which haven't been merged or completely isolated repos that produces patches only. Keeping track of all requirements in the former is hard, especially if the dev doesn't know git pitfalls. No one should default to rebase in a day to day workflow, but it is quite common.
Rebase is mostly useful for cleaning up local commits or feature branches. You can rebase without force pushing master.
driving can be dangerous, but so productive. I think it's important to each new adults how to properly use it.
You already have git-revert, for reverting commits without rewriting history.
You're misunderstanding the purpose i'm describing. Imagine 100 commits a day, maybe more. (I worked at a company that averaged 500 or more commits a day to the master branch. There were 1000 developers working in a monorepo). Some code is out in production, and suddenly we realize a specific commit is causing a problem. The idea here is to revert the commit as soon as you can, and then spend your time fixing it. When reverting code is easy, and the company has good logging to identify problems, you can deploy more often. It's a good thing.
But to enable this "revert-first" culture, you have to design your commits to basically be super easy to revert. That means no merges in the master branch, you want to keep your revision history as clean as possible. One commit, as little dependencies as possible. Rebase is the right tool to use for this. The goal is a tidy linear history.
5 replies →
Git revert has undesired side effects for merges. If you have a merge-only workflow (GitFlow, for example), and your pull request breaks something, a revert commit will not help you.
After a revert, all the commits that were merged, are still merged, but then they're deleted. The next time you pull, git will delete the changes in your working branch.
In a merge workflow, you have to either fail forward (fix the problem, rather than backing out the merge), or reset/rebase the shared branch, and email repair instructions to everyone on the team.
7 replies →