6 ms·
My only real git crisis was when I accidentally `git push -f`ed what I thought was my own branch, but actually the `develop` branch. On a monday. After a weeken
by mmanfrin 11y ago
My only real git crisis was when I accidentally `git push -f`ed what I thought was my own branch, but actually the `develop` branch. On a monday. After a weekend where about a hundred commits had been cherry picked and merged in to develop by a dev not in the office. None of my coworkers had recent versions of develop.
The thing that ended up saving me was our CI -- we autodeployed passing builds to our staging env; so we were able to ssh in and `git push -f` back from staging to our repo.
- jordigh 11y agoMercurial Evolve is a safe and distributed alternative to `git push --force`: https://www.youtube.com/watch?v=4OlDm3akbqg https://www.youtube.com/watch?v=4OlDm3akbqg
- herge 11y agoFor what it's worth, you could have looked at the reflog of the git repo on the server and it would still have a reference (the hexadecimal hash) to the develop branch before your git push -f.
- mmanfrin 11y agoWe had the hash, but no one had it locally and we could not pull it down since I had overwritten the history.
- simoncion 11y agoThis isn't a criticism. I'm either missing info, and am making a fool of myself, or telling you about something you didn't know was possible: You either had git configured on the server to git-gc after every push, or were unable to ssh into the server? If neither one of those is true, then -IIRC- you could have either: 1) Logged in to the server, rewritten the affected repo's branch to point to the pre-disaster commit hash. 2) Pull down the repo's .git directory from the server, rewrite the branch, and force push that. Would either one of those have been more work than working with your CI system?
- dsp1234 11y agoGit generally doesn't delete commits until a garbage collection is done (and assuming no other references). If you find yourself in this situation again, then try: git reflog show remotes/origin/develop This will show the reflog for the branch, then you can find the hash just before your push, check it out, then force push it back. I've recovered from other developer's accidental force pushes in less than 5 minutes, with no commits lost.
- jordigh 11y agoBut if the remote has advanced since you pushed, you'll still need to reflog on the remote server, right?
- lmm 11y agoSomeone must have pushed the version the remote was at, so the correct commit would be on someone's devbox.
- mmanfrin 11y agoIt was a series of PRs merged on github, no one in the office had a current branch of develop.
- dsp1234 11y agoIt looks like you can use the GitHub API to get the events for the specific repo, which would include your force push, and the hash of the previous commit. Some instructions at https://objectpartners.com/2014/02/11/recovering-a-commit-from-githubs-reflog/ https://objectpartners.com/2014/02/11/recovering-a-commit-fr... edit: This should be in reply to jordigh's comment above
- lmm 11y agoIf it's just a matter of "merging" couldn't you just merge those branches again? Or do you resolve conflicts on github or some such (something that's never fit my workflow but I can imagine others using it)?
- _ikke_ 11y agoI always recommend people to use `git push --force-with-lease`. It's more to type, but it verifies if the remote branch is the same as the remote tracking branch, so you don't accidentally rewrite branches someone else has pushed to.
- rectangletangle 11y agoYou can just alias it in your bash profile, if it's too much to type. alias gitpushf='git push --force-with-lease'
- Peaker 11y agoJust make an alias pushf = push --force-with-lease, and it becomes even less to type! :-)
- matwood 11y agoPlaces like bitbucket let you mark branches (like master and develop) as non-deletable and non-rebaseable. Basically it prevents errors like yours.
- smtddr 11y agoSeriously. I don't understand why github doesn't provide at least the ability to lock the master branch against any action other than a merge from another branch. Merging a branch that causes major damage is unlikely if there's any kind of review process and generating a revert to "undo" that damage is a one button thing in the github-webUI if you do it immediately, or at least before master gets other commits on top of it. But I'd think everyone's workflow would stop because they'd have a ton of conflicts from a screwed up master. In fact, let me ask HN. Does anyone work in a place where devs commit directly to master? I can't even imagine that workflow. Everything I've seen or heard of is PullRequests, code-review, +1, then merge to master.
- yawaramin 11y ago> Everything I've seen or heard of is PullRequests, code-review, +1, then merge to master. That won't help you when you think you're pushing to and from your own branch, but are accidentally on develop and force-pushing to the remote develop branch.
- detaro 11y agoBut if your process is only merging PRs, then locking the master against pushes as he proposes would create no further issues, preventing that from happening. If you need to modify the master directly, it would complicate things.
- deleted 11y ago[deleted]
- matwood 11y agoThat's where locking down the branches and preventing rebases comes into play. It prevents someone from accidentally doing what you describe. Most people only know github and I don't think they expose this locking feature in their UI which is a shame.
- chjj 11y agoMy most recent major git crisis wasn't reversable by git. A little while ago, I accidentally did a `git clean -xdf` on my home directory (wrong tmux tab). I index my home directory: just the most important config files, among other notes and text files. That `git clean` call wiped half my home directory before I realized what was happening and frantically tried to ^C and ^\ it. I had to find other ways to recover my files. The deleted files weren't essentially important, which is why I didn't back them up frequently or index them, but they were moderately important. That was a bad day. I realize it's probably better to dump everything in ~/.config and index that instead, while maintaining symlinks in ~/. It was just the way I had it set up.
- ossreality 11y agoYou know to fix this? Symlink your bullshit in ~/ to some other directory. I have a "my_config" repo on GitHub that contains personalized home files. Shockingly!!!!! they're not stored in my home directory because that would be an absurd idea! Instead .{vimrc,profile,bashrc} are symlinked to ~/code/{mysusername}/my_config/{_vimrc,_profile,_bashrc). Guess how many times I've wiped out my home dir? (it's zero, zero times)
- leni536 11y agoI suggest to use GNU stow for managing config files and keep your repo in a separate directory.
- tomjen3 11y agoHow is this not undoable with whatever the reverse merge command is? Second why ever use force merge?
- erikb 11y agoMaybe that was why I always `git fetch && git push -f`. But luckily since a few months it's not a problem anymore if you configured your git correctly, because now it only force pushes your current branch.
- Peaker 11y agoJust make an alias pushf = push --force-with-lease, and it becomes even less to type! :-)
- Kiro 11y agoWhat kind of workflow do you use where a git push -f is necessary? Just curious, I'm no git expert.