19 ms·
Oh shit, git (2016)
- saagarjha 7y ago> I committed and immediately realized I need to make one small change! I think it might be nice to add a disclaimer saying that this is not advisable if you've already pushed the code. Suck it up and make a new commit–don't rewrite public Git history.
- arcticbull 7y agoThis is indeed a job for git revert, push/pr, check out a new branch then revert the revert with better messaging :)
- colatkinson 7y agoI think changing history is fine on feature branches that only you are working on, though. IMO the benefits of keeping commit history clean outweigh the cost of having to push with "--force".
- fulafel 7y agoThis then discourages ad hoc teamwork because you can't touch feature branches other than the ones you own. And because the results of getting it wrong are hairy, people will tend to stay away just in case. It's a chilling effect. Or, someone might have created another branch off your feature branch, because they depend on your work. Now you've creaed a time bomb for them when they try to merge their work after you've merged your alternative-history version of it. (and the failure mode is just weird, it takes experience to identify that all those seemingly nonsensical merge conflicts are result of this situation) Etc. It just breaks a lot of things. The Git model and bad UI are already taxing enough to work with in your head, concurrently with your actual programming and domain cognitive load, that adding the uncertainty and multiplied complexity from having history rewritten around you is just a bad tradeoff. (This may be different if the scenario is not a team, of course...)
- serpi 7y agoyou just rebase on top of their changes. No biggie here. It does not matter one bit if their branch rewrites itself underneath.
- fulafel 7y agoBut you can't safely rebase that branch! Having rebased it, you would have now broken it for others working on it. So this is a great example how the damage spreads and taints other branches around the history rewrite. (And even arriving at the "ok i could fix this with rebase" diagnosis will have been painful and frustrating and eaten time & energy, and you can't be sure you got away with it before actually doing it and waiting if your teammates will come kick you in the nuts. or worse, silently spend a day untangling their work.). It's just fundamentally unsound.
- mehrdadn 7y ago> But you can't safely rebase that branch! Huh? You don't rebase their branch. You rebase your own changes on top of their branch, which they happened to recently rewrite. Just like you might rebase your changes on top of master after master has undergone changes. I think the parent's point was that it doesn't matter if the branch was rewritten or just extended; either way you rebase the same commits on it the same way. (If you're one of those people who's against the notion of rebasing entirely then that's a separate debate we can have another time, but you need to separate that from the force-push issue.)
- lixtra 7y agoI find it okay to rewrite public history in short lived feature branches. It’s typically your branch after all. So it would change your advice to: Don’t rewrite public Git history unless you can assume it’s read only. Patches for Linux get rewritten all the time till they are finally merged.
- broodbucket 7y agoThat's not public git history though, those are just patches on mailing lists. Even before it goes into maintainer's lists, in my experience it's extremely rare that a maintainer will force push to their own public -next branch.
- lixtra 7y agoEDIT: parent is right. I see about 600 pull requests on github[1]. My understanding was that Linus moved away from mailing lists some time ago. But then I'm not involved in kernel hacking. [1] https://github.com/torvalds/linux/pulls https://github.com/torvalds/linux/pulls
- clarry 7y agoDid you ever look at any one of these PRs?
- saagarjha 7y agoThe Linux kernel has a bot that reminds people that kernel development happens on the mailing list: https://github.com/KernelPRBot https://github.com/KernelPRBot. Since GitHub does not allow for disabling the pull requests tab, the pull requests invariably get closed.
- scarejunba 7y agoI force-push all the time in my feature branches. It's expected. If I'm using `git commit --fixup` and `git rebase -i origin/master --autosquash` that feature branch is going to come out clean and nice in the merge commit if I force push to my feature branch.
- groundCode 7y agoLike a few other replies, I force push on my branches all the time. I push my code up to my origin as soon as I can and as I go I’ll fix up my commits and force push. There are some advantages for me anyway. Pushing to origin kicks off some smoke tests and end to end tests that are fairy slow and cumbersome to run on my dev machine. That helps me catch bugs earlier, especially since I’m working on a Microservices architecture. Also it acts as a backup for if my dev machine dies on me. I prefer to fix up and force push to create a clean logical story from my code rather than leave in spurious commits which exist only to fix linting for example.
- the_gipsy 7y ago> Suck it up and make a new commit–don't rewrite public Git history You're most likely making things worse. Not only will you have the mess-up commit(s), but also the un-mess-up revert-commit. It gets super hairy when reverting merges (I assume you're not rebasing + fast-forwarding if you lobby against rewriting). There is no big deal in rebasing to a rewritten master branch. It's just like any other rebase. IMHO, rebasing signals that someone wants to apply a patch, and knows exactly where. Merging/reverting/etc. signals someone wants to "upload his latest stuff", like to a dropbox.
- rich-tea 7y agoGit is not hard. It's very simple. But people learn it the wrong way. You have to learn it from the DAG up. If you cannot grasp how the DAG works you'll forever be reading and writing articles like this one which do not help you to learn. This is a horrible article. You should not bookmark it or use it. If you're not a programmer, you shouldn't use git. If you are a programmer, do yourself a favour and spend a day going through something like this: https://wyag.thb.lt/ https://wyag.thb.lt/ It will make you better at git and better at programming. Git is a powerful tool and you need to learn how to use it. Imagine if people read articles like this one instead of learning how to drive.
- wishinghand 7y agoWhat's a DAG?
- kccqzy 7y agoDirected acyclic graph. Basically each git commit points to zero or more parent commits (usually one, zero for root commits, more than one for merge commits) and that forms a DAG.
- yaseer 7y agohttps://medium.com/girl-writes-code/git-is-a-directed-acyclic-graph-and-what-the-heck-does-that-mean-b6c8dec65059 https://medium.com/girl-writes-code/git-is-a-directed-acycli...
- rich-tea 7y agoUnfortunately this article, like almost all others, is still wrong because it looks like commits get mutated when you rebase and the old commits disappear. It is very important to understand that commits (in fact, all blobs) are immutable in git. You can only make new things. You can't modify old things. Git doesn't delete anything for a while either.
- masklinn 7y agoDirected Acyclic Graph. Graph = graph, a structure composed of a set of objects (nodes or vertices) with links between them (edges). Directed = the edges have an orientation / a direction. Acyclic = there's no cycle, you can't come back to a node (in a directed graph you have to follow edge direction). In Git, the commit objects are nodes, the "parent" link(s) is a directed edge, and because commit objects are immutable you can't create a commit which refers to one of its "descendants" and thus the graph is acyclic.
- dang 7y ago2017: https://news.ycombinator.com/item?id=15951825 https://news.ycombinator.com/item?id=15951825 2016: https://news.ycombinator.com/item?id=12459755 https://news.ycombinator.com/item?id=12459755
- scarejunba 7y agoHonest to god, I don't know how people who find `git` hard to use manage to write code. Everyone on the Internet acts like the concepts are impossible to grasp and it's like really easy to grok. Honestly, it faded into the background of code from the beginning. I mean, I know "Forward-port local commits to the updated upstream head" means nothing to anyone not already familiar with `git rebase` but a practical mastery of the tool is very easy to achieve. I honestly think this is a pedagogical lack. We tell everyone it's this complex thing and that they should be scared of rebase and the reflog and they believe it. Maybe if we didn't, it'd be easier.
- thatoneuser 7y agoOK hot shot. Tell everyone here how you've never fucked up commands and had to blow out a repo and start over and how were all idiots for having done that. It's a tool. Any tool can be confusing if the person isn't taught how to use it. Git requires teaching so there's a lot of room for misunderstanding.
- scarejunba 7y agoI'm not the hot shot. The hot shots are all the kids from Berkeley and Stanford who figure this shit out as interns while supposedly fully-trained engineers with all the knowledge of data structures that should come with that think this shit is too hard. I think I'd be completely unsurprised to see an intern successfully use `rerere` on a longer project of theirs.
- darkpuma 7y agoI know of teenagers who happily use git because nobody ever told them they were supposed to consider it hard.
- scarejunba 7y agoThis is exactly what I’ve seen. Thank you for validating that viewpoint. Without being told they’re going to find it hard, they just rapidly build a model of how to interact with the tool and how it improves their life.
- dnprock 7y agoReading this article, I realize that I'm old now. I still remember wrestling with cvs, svn. Merge, branch were slow and even more challenging. It was much easier to mess up and so difficult to rewind. When I first learned git, I thought it's pretty neat. It solves merge, branch, rewind problems. Git is one of the things in life that doesn't work like the way we think. But it turns out to be a better way.
- jchw 7y agoI’m torn. Practically Mercurial feels like it should be the winner. The commands are more uniform and predictable. That’s not all it has going for it either. Mercurial has a concept of commit stages to make history rewriting safer. It has a commit model that enables you to work on and manipulate branches of commits seamlessly, without needing named branches. It has not just a tree of commits but also each commit tracks its own history through rewrites. You get cool commands like absorb and evolve. It’s easier to extend than Git. The only downside to modern Mercurial I can think of is it’s still slower than Git, by at least a bit. But it can scale incredibly far with its extensibility. For example, what Facebook did: https://code.fb.com/core-data/scaling-mercurial-at-facebook/ https://code.fb.com/core-data/scaling-mercurial-at-facebook/ So why does it never seem to get consideration? I guess it’s because of the insane proliferation of Github and Linux, which is definitely more a blessing than a curse. But it’s weird. Back in the CVS and SVN days, it didn’t seem like there was ever going to be a ‘network effect’ for source control like there is today. I kind of wish Gitlab would implement Mercurial support. I bet it would help Mercurial gain more adoption within teams working on closed source projects. I know Bitbucket does, but to be honest that doesn’t really appeal to me much.
- darkpuma 7y agoHg and git have near feature parity, so I don't really lament Hg's loss so much. Sure Hg's CLI is a little bit better, but beyond that it never really offered any really compelling features over git. Mercurial and git is like Honda and Toyota; maybe one is a bit nicer than the other, but they're both offering you more or less the same thing. Fossil is another matter. Fossil defies pithy car analogies. Integrating the bug tracker into the version control alone is a game changer, and that's not even all that Fossil does.
- ddtaylor 7y agoMany of these problems can be avoided by using a pull-request style workflow.
- reacweb 7y agoYes, there is a balance between preventing problem or fixing problem. It is useful be prevent problems, but it remains useful to be able to fix them easily.
- aflag 7y agoI don't see how prs would help solving any of those. It's common for me to use a few of these commands before I open the PR.
- Sammi 7y agoThey stop you from pushing anything broken to master. So you only have to worry about being in a broken state locally on your machine, not about accidentally breaking master for everybody. Ideally your code review system should be the only one to have merge rights to master. Then nobody can singularly break master at least.
- dahart 7y agoHow? I don’t see a single issue in the post that a PR would avoid. All the problems listed happen before you’re ready to push or present to others.
- vijaybritto 7y agoThis has been immensely useful every now and then
- _pmf_ 7y agoI don't get this "afraid of losing something" mindset at all. In fifteen years, I've "lost" some minor changes maybe 3 or 4 times, and this was mostly with SVN, which does not have the safeguards that Git has. The only thing that I am moderately afraid of is pushing to the wrong remote branch.
- gvd 7y agogit reflog
- mehrdadn 7y ago> I don't get this "afraid of losing something" mindset at all. In fifteen years, I've "lost" some minor changes maybe 3 or 4 times, and this was mostly with SVN, which does not have the safeguards that Git has. The only thing that I am moderately afraid of is pushing to the wrong remote branch. I can lose something for you in 2 seconds in git. Have fun e.g. recovering from this: $ git init $ mkdir -p widget && echo Introduction > widget/readme.txt $ git add widget $ git commit -m "Initial commit" $ echo Conclusion > widget/readme.txt $ git checkout widget $ cat widget/readme.txt # No "Conclusion"??
- fileeditview 7y agoWow just tried this.. is this considered a bug or a feature and where can you read about this if it is intended behavior?
- mehrdadn 7y agoProbably a feature given how many gazillion meanings they've given to checkout intentionally, but I have no clue. Hopefully it got the point across though ;) and I'm pretty sure it's not the only way to lose info in git...
- bicolao 7y agoIn a near future, hopefully we will have two new commands, git-switch and git-restore. The former is only about switching branches, the latter restoring files. Then you can stay away from the overloaded git-checkout. See https://github.com/git/git/blob/pu/Documentation/git-switch.txt https://github.com/git/git/blob/pu/Documentation/git-switch.... https://github.com/git/git/blob/pu/Documentation/git-restore.txt https://github.com/git/git/blob/pu/Documentation/git-restore...
- dwaltrip 7y agoGit is pretty nice, but I'm sure there is something much better waiting to he invented. The CLI in particular could use a ton of improvements. And I feel it in my bones that there is a revolutionary GUI waiting to be invented. Why can't I drag a commit or set of commits from one branch to another? With safe, easy undo (reflog doesn't count) and super smooth conflict resolution? Etc etc. And of course there is the interesting rabbit hole of semanitc / language aware diff. Line diffs suck in many ways. It's one of the hundreds of of problems that I'd love to work on one day, but probably won't get a chance to. Sigh... :)
- rk06 7y agohttps://gitless.com/ https://gitless.com/
- saagarjha 7y agoCan this tool make the commit history look like I'd like it to?
- jayd16 7y ago>and super smooth conflict resolution? Because the hardest part of conflicts is already the conflicting changes themselves and not the source control.
- IshKebab 7y agoSure but I've never found a GUI or editor that lets me resolve conflicts in the way I want. For example say I change one line of code in a big function. I rebase and that function has moved. Conflict! I want a tool that says "here's what you changed, and here's the current state of the source". None of them do that though - they all just show the conflicts that git writes to disk - the code after you changed it, and the current code. You basically get two copies of the function, one with your change and one without and you have to manually (visually) diff them to work out what you changed (or go back and look at your commit) and then reapply that change to the moved function. It's really awkward and could definitely be better.
- sadness2 7y agoI prefer this, because it has a flow-chart http://sethrobertson.github.io/GitFixUm/fixup.html http://sethrobertson.github.io/GitFixUm/fixup.html
- reacweb 7y agoOh shit, this commit message buried by new commits must be fixed before it is propagated to other repositories. Oh shit someone has fixed an old commit message that was already pushed to other repositories. Oh shit, this commit ough to be a merge commit. The tree is good, but not the parents.
- dzdt 7y agoAm I the only one who reads "reflog" as "re-flog", that is, to be painfully whipped again?
- diegoperini 7y agoYou are not alone.
- jrochkind1 7y agoI knew about it for at least a year thinking it was "re-flog", and just considering it mysterious why they would have called it that. (You do often use it for "re"-doing things, maybe it's got something to do with that?) Hey, it was (and is) hardly the only mystery to me in git UI. Then like a year on I suddenly realized Ohhhhh it's ref-log, that makes a lot more sense!
- jsilence 7y ago.oO( the beatings continue until morale improves! )
- lunchables 7y agoI will now forever. Reminds me of when you read "therapist" as "the rapist".
- bloopernova 7y agoIt's always Sunny in Philadelphia ruined "philanthropist" ("full on rapist") for me, forever.
- ghiculescu 7y ago> git reset HEAD~ --hard Seems fairly magical compared to other stuff here. To me at least. Can anyone briefly explain what it does?
- q3k 7y agoHEAD~ means 'the second to last commit in the current branch' (ie. the second to last when you `git log`). git reset means 'point the current branch to this commit instead of wherver it's pointing now' (branches in git are just pointers to commits) git reset --hard means 'also reset the state of the checkout and staging area to be in sync with the commit' Thus, the entire spell means 'reset the current branch to make it point the the seecond-to-last-commit, also ensure my current checkout and staging area are in sync to that', or, in other words, fully forget and drop the latest commit.
- gwright 7y ago[Edit: It seems that I was mistaken but I'm leaving this up to illustrate the confusion. In my experience "second to last" isn't common and "next to last" is much more common, which I think is why I was confused because I thought they were different, but apparently they are the same. I wonder if there is a regional usage pattern to these phrases. ] This seems like mistake or a non-standard usage of the english phrase "second to last". Given a git log of: $ git log --oneline 15e0437 - (HEAD -> master) this is the third commit f82d1fd - this is the second commit 9180c17 - initial commit I would call "f82d1fd" the "next to last commit" and it can be referred to as HEAD~ I would call "9180c17" the "second to last commit" and it can be referred to as HEAD~2
- gpvos 7y agoOne thing that I had been looking for for a long time, but never could find, was a description of the several syntaxes you can use to refer to specific commits. Lots of git tutorials use these magic incantations, but none point you to this crucial bit of explanation. Recently I discovered that it is found under "git help revisions".
- xelxebar 7y agoOr just gitrevisions(7). The manpage for git(1) mentions this under the section SYMBOLIC IDENTIFIERS. Not that that's the most obvious place to look, but if you rtfm the obvious stuff, you should stumble upon these gems naturally. It's worth scrounging through git(1) anyway; it mentions several other manpages for things like recommended workflows, the basic structure of the .git/ directory, not to mention gittutorial(7).
- gpvos 7y agoIn git(1) it's below LOW-LEVEL COMMANDS (PLUMBING). You cannot expect a novice to read thoroughly past something like that. And it's remarkably hard to find using web searches, since most git documentation uses the term "commit" for these things, not "revision".[0] I found it after I discovered "git help -g", which lists "some concept guides" according to "git help". Of course, n=1 and stuff, but there's a lot about git that is not obviously documented. Something like this should be linked to in multiple places, so even if you skim over one you'll catch it relatively early. [0] The name of the man page was chosen to avoid conflict with the "git commit" command, I guess?
- Sammi 7y agohttps://git-scm.com/docs/gitrevisions https://git-scm.com/docs/gitrevisions
- js4ever 7y agoThanks for this excellent cheat shit
- BuildTheRobots 7y agoThe last example [0] really should reference the obligatory XKCD [1] [0] https://ohshitgit.com/#fuck-this-noise https://ohshitgit.com/#fuck-this-noise [1] https://xkcd.com/1597/ https://xkcd.com/1597/
- systemBuilder 7y agoGit performs like what it is : a piece of code created by debugging a blank sheet of paper. I can detect almost no philosophy and no simplifying assumptions. The thought that you need 60+ commands (the current size of my git cheat sheet, including all the bizarre argument incantations which seem customized for all 100+ possible mistakes in git) to get through the day is an abomination. I prefer perforce which requires less than 20 commands. The only reason people use git is because, Linus. Like no good program, ever, to use git you have to understand all the compromises and all the internals of its data structures. What a joke.
- spenrose 7y agoSame idea, but much more comprehensive: https://github.com/k88hudson/git-flight-rules https://github.com/k88hudson/git-flight-rules
- jancsika 7y ago> git diff --staged The way it worked well was that the "--staged" flag would be implied if you had already staged some files to be committed. But on this day I noticed that nothing bad happened from that behavior. So I time traveled back and whispered to the git devs that the interface should be made more pedantic to keep users from relying too much on git to do the right thing for them. Now it's great because users suffer and I have plausible deniability from this now being on par with the rest of git's interface.
- zoomablemind 7y agoGit is nice tool, very versatile in able hands. Thanks to its promotion (plugins and github included), the pragmatic practice of source versioning gained wider adoption and lost that beg-your-IT-dept-to-set-it-up flair. In the mean time, 'thanks' to Git, the source change history became a maintenance line-item. The expectations of a clean history were raised almost to the level of expectations for bug-free code. I can see a utility of clean feature history, but asking developers to craft the history is shifting their focus away from the actual code. As long as the source state has been saved, the source control has done its main job. So for the most of the listed 'shits', the developer should just be able to revert, cherry-pick, and re-commit, and keep going. Nothing esoteric and hard to remember, also fairly common commands across different VCS tools. Shit happens and will happen again, no biggie, no need to blame and shame, source annotation will show the right change/comment anyway.
- luxcem 7y ago> I use reflog A LOT If you need to reset with reflog a lot you're probably using git wrong. Sure it can be useful but I don't see why it should be in a workflow.