
Oh shit, git: Getting myself out of bad situations - adishaporwal
http://ohshitgit.com/
======
lwansbrough
Adopted a git GUI years ago and haven't looked back. I get looks sometimes,
but I can't help but gloat when I can stage and unstage individual lines in
less than a second.

I think anyone who uses the CLI is either trying too hard or hasn't realized
the beauty of a git GUI.

Takeaways:

\- My commit time is usually much faster than coworkers, with higher accuracy
(less frequent accidental commits, etc.)

\- I don't remember the last time I made an irreversible change to the repo,
or had an "oh shit" moment. And that's despite using some interesting git
features.

\- Staging individual files, folders, lines of code, or hunks is easy. Makes
maintaining multiple trains of though / addressing bugs while working on other
code a non-issue.

\- It's easy to keep files uncommitted for long periods of time intentionally,
without slowing down my workflow.

\- It's much easier to get an overview of the changes I'm making.

~~~
emeraldd
What GUI do you recommend? My experience has been that GUIs are the easiest
and fastest way to make a mess that can't be corrected without dropping to CLI
or re-cloning. (I'm looking at you SourceTree). I've long recommended that
everyone who uses git know how to use the CLI even if they don't use it
regularly.

~~~
welly
If you're on a mac, I can't recommend Tower enough. It's a paid app but well
worth the money. Otherwise Git Kraken is a foss offering that is also
excellent.

~~~
Froyoh
How is atlassian's Sourcetree?

~~~
prewett
I like it a lot, it make git as simple as mercurial. I don't think it is
hiding complexity, but the visual arrangement makes sense. The staging area
becomes actually useful, and I love that you can stage (or revert) pieces of a
file, which is handy when you forgot to commit one thing before moving on to
the next.

I've only had to merge a branch once, and here I was completely confused on
what was going end. This may be SourceTree's fault or git's fault. Maybe my
lack of understanding.

I hate git, I don't understand git, I don't want to have to understand git,
and I think the command line interface makes every UI error in the book. But
SourceTree has made me like git.

------
falcolas
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.

~~~
swalsh
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.

~~~
falcolas
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.

~~~
Yokohiii
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.

------
greysteil
Nice. For anyone who hasn't see it, Flight Rules for Git is even more
comprehensive: [https://github.com/k88hudson/git-flight-
rules](https://github.com/k88hudson/git-flight-rules)

~~~
taoistextremist
I'm planning on making a hard push for git on the team I just joined (that
isn't using any VCS). This and OP are going in my bookmarks.

~~~
pc86
I'm genuinely curious how they manage source without any VCS. Is it just a
bunch of zip files for old versions?

No judgment, nobody is born knowing this stuff, just that I'm surprised to
hear this is still out in the wild.

~~~
taoistextremist
We SSH onto a server to do work and it seems we just make folders wherever for
our individual projects. They do (nightly, I think) backups which is sort of a
rudimentary version control. And while I'm told it exists, it seems the "dev"
version of their website isn't used, so they just kind of add in their changes
live; definitely a risky environment. They've had a small team for a while and
most of their applications could run relatively in isolation from others, so
they could get away with it, but they're looking to grow so I'm trying to push
this stuff.

~~~
pc86
Yeah the "right way" to do VCS is definitely a lot of overhead for a team like
that, but by the time you need to scale up (and by "up" I mean 3-6 people
total who are committing code multiple times daily?) the business is likely so
busy it's a HUGE uphill battle to implement something like that, especially
since most of the people who let an environment like that happen will likely
not be super familiar with Git/hg/TFS/whatever.

~~~
rdiddly
I dunno if I'd agree that it's a lot of overhead, for what you get back. Hell
I'm a one-man team right now and I'm using source control. Some of my little
experiments go horribly awry. Some of my deletions are a bit too
aggressive/arrogant. Sometimes you need to diff shit. Version control frees me
to be bold.

~~~
minor3rd
Agree with you here. I use git for literally every coding project, even my
quick practice folders. I haven't had an "oh-shit" moment from losing anything
in like 5 years, back when I was still learning git.

------
herogreen
In three years of using git I believe there is a single bad command that I
could not undo: `git checkout -- somefile` The second worst thing I did is
losing a commit in a `git rebase -i` but I was able to find it back with `git
reflog`. Which makes me think that git is really well designed.

~~~
anton_gogolev
If by "designed" you mean "picking a content-addressable DAG as an underlying
data structure", then yes, it is really beautiful. If you mean "provide a sane
level of abstraction over said data structure", then hell no!

~~~
jimktrains2
I think git provides a sane level of abstraction.

I don't think it provides the most consistent UI or helpful help, though. Once
you move away from "learning git commands" to "learning how git works" and
kind of figuring out which parts the commands refer to has helped also. That's
still terrible though.

~~~
ivix
>I don't think it provides the most consistent UI or helpful help, though.

Understatement! Git is one of the most user-hostile tools I've ever seen. And
I've used Sendmail.

~~~
pqh
Just read the manual.

[https://git-scm.com](https://git-scm.com)

------
sfink
You could also use an alternative CLI for git. My preferred one is hg-git.

I'm sort of kidding, but not really. By using it, I can operate on a git repo
using the mercurial CLI, which I am more comfortable with and have built
tooling around.

Once you have the extension installed, it's a matter of prepending 'git+' to
the beginning of eg a github url to clone it, and then you can use native
mercurial commands.

Obviously, this is an extra layer with all of the problems that involves (eg
you're going to be managing git branches through an hg interface. Which works
surprisingly well most of the time.) So this makes NO SENSE WHATSOEVER unless
(1) you are comfortable with the hg interface, (2) you aren't that comfortable
with the git interface, and (3) you don't need to do complex operations that
would require thinking through the layers of what is happening.

Honestly, though, if I want to contribute to a github repo, this gives me
everything I need 95% of the time. So far, the only time I ran into trouble
was when the active branch was renamed in the github repo. Things got very
tangled up, and I had to re-clone and import my patch stack. Judging by the
number of people talking about making "backups" of git repos in this comment
section, it doesn't sound like that's an unexpected operation in git-land.
With mercurial's immutable and append-only nature, I very very rarely need to
do this, so it felt kind of awful.

(Admittedly, my main hg repo that I work on is 6GB and I'm normally near the
limit of my disk space, so my habits don't really match your typical megabyte-
sized github repo in some noncompiled language.)

------
mFixman
Honestly, a lot of what's wrong in git is that people seem to mostly memorize
or copy-paste a finite amount of commands, and when something goes wrong they
are completely lost unless they can find a way to copy-paste a solution.

Instead of saving a 6 command list for some use cases, why not just get used
to the simple but kinda unintuitive way of how revisions and branches work? If
you know that, you can solve any problem with `commit`, `checkout`, `reset`,
`reflog`, and occasionally `cherry-pick`.

~~~
CJefferson
Quick quiz, what does 'git checkout x/y' do? I am aware of users hitting at
least 3 interpretations.

~~~
Nimitz14
I'd say it changes your code to match that of a branch in your local copy of
the repo.

~~~
CJefferson
It resets the file x/y, or checks out branch y of remote x, or checks out
local branch x/y. I've had confused users manage to create al of these cases,
and git is very unhelpful in explaining the difference between the three
cases.

------
compiler-guy
The fact web pages like this exist, and are popular, and make it to the top of
Hacker News is all you need to know about git's ease-of-use and mental model.

That Perforce and SVN don't get such things should also tell you something.

(Which isn't to hate on git--it's a great tool.)

~~~
forrestthewoods
Threads like this are a nice reminder of how nice it is to use Perforce.
There's no such thing as getting yourself into a bad situation. Not even for
artists or designers.

Git has eleventy million blog posts trying to explain how simple it is to use.
That's a clear sign that it is, in fact, not simple or easy.

~~~
accatyyc
Reminds me of all articles attempting to explain how simple monads are

------
tnolet
Good thing HN doesn’t have memes, otherwise I would post one of those bears
confessing “I’m a software engineer with 19 years of experience and I still
don’t really understand git”.

Silliness aside, I guess Git suffers from the trait that it is very hard for
many people to internalize and visualize how it works in their heads. Totally
different but related: the Azure CLI is for some reason 10x easier to work
with than the AWS CLI, while I’m 10x more experienced with AWS. I guess CLI
design is also design.

------
hitekker
I like using IDEA, PyCharm's and Webstorm's "local history" feature to
compensate for gaps in my git knowledge.

A constant, instant backup of all files, independent of the repo, has been my
saving grace for small projects.

~~~
vbuwivbiu
\+ it shows you a diff with the ability to revert individual changes in code

------
anotherevan
“Git gets easier once you get the basic idea that branches are homeomorphic
endofunctors mapping submanifolds of a Hilbert space.”

— Isaac Wolkerstorfer (@agnoster)

------
grawprog
My last git mistake was pretty terrifying. I decided to try and go back to an
old commit on a project on my local machine after about a days work. Somehow I
ended up making the commit I wanted to revert to a new branch, then somehow
tagged that branch with the name of the commit making git get angry and decide
that branch wasn't valid. Then continuing in my ignorance I reset to that
branch and tried to checkout only to watch my source and resource files vanish
one by one. Deciding the commandline had caused enough trouble I returned to a
qgit window I had open, all the source files were still there and I could at
least save them one by one. Better refresh the qgit window. Oh shit now qgit's
mad at me too. Well there goes thousands of lines of code and about 3 months
worth of work. Eventually,after reading gits cryptic error messages and a few
google searches I figured out how to remove a tag from a branch and properly
checkout an old commit. I was really happy when all those source files
reappeared.

~~~
mynewtb
Git is not a backup! Had you had one, you could have had your mind at ease.

~~~
rootlocus
Pushing to a remote is a backup. Gitlab offers private repositories for free.

~~~
dsego
Until you force push ;)

~~~
rootlocus
And then you still have the commits, but no branch pointing to them. Don't
worry, they're still there.

------
dkns
> Oh shit, I accidentally committed to the wrong branch!

I find cherry-picking to be easier in this case. Just checkout the branch and
cherry pick commits from 'wrong' branch.

[https://git-scm.com/docs/git-cherry-pick](https://git-scm.com/docs/git-
cherry-pick)

~~~
mtrpcic
But then those commits are still in the wrong branch. If I accidentally commit
something to master instead of a development branch, I can't deploy master
until my development branch is merged in, as the one commit isn't ready for
live.

~~~
mseebach
If you haven't pushed, it's as easy as resetting the branch to the last good
commit. If you have pushed, well, it's the same, then push -f, and then making
sure that all your teammates pull the fixed branch. If that's a situation you
regularly find yourself in, protecting master from direct pushes and only
doing PRs is a good solution (GitHub, BitBucket and GitLab all have tooling
for this).

~~~
dkns
Maybe it's just me but I feel like if you work with multiple developers you
should never, ever force push master. I'm wary of force pushing branches in
general, unless that's a branch that only I work on.

~~~
mseebach
It's not ideal, at all -- and if someone else has pushed in the meantime, they
risk losing the commit. But if you're in a situation where doing this would be
a significant problem, you should probably not be pushing directly to master
in the first place, instead relying on a PR workflow.

~~~
sigjuice
Why not simply push a second commit that reverts the broken commit? This will
avoid rewriting history and messing up the rest of your team.

~~~
mseebach
Because that will pollute the history and diminish its value as a record of
what happened in the code base. For instance, blame will no longer tell you
when a line was changed, but rather point to the revert commit. Bisect breaks
if it divides through the reverted commits.

Of course, rewriting history is only feasible immediately after the mistaken
commits, before anyone builds on top of them. If they've lingered, reverting
is the right way.

And again, if this is a repeating problem, fix it upstream (no pushing to
master, only PRs).

------
Waterluvian
I gave up on rebasing or any form of history rewrite after going through the
screw up phase, then watching every dev that came after me do the same at
least once.

I realised that treating a git repo like an immutable collection, where
existing commits are NEVER mutated makes it far easier to reason about history
and nearly impossible to do serious damage.

Devs can do whatever they please with their own local pulls (such as squashing
50 rambling commits during dev), but once a commit is on remote, it never
changes.

------
gerbilly
On barrier to learning git is that people are understandably reluctant to try
things out because they are working in real repositories.

This site makes a game out of learning git:
[https://learngitbranching.js.org/](https://learngitbranching.js.org/)

It's a great way to learn without putting your real repository at risk.

~~~
degenerate
Thanks, I am new to git and already made some dumb mistakes with my real repo
and had to start over. Now I'm terrified to try anything past pulling and
pushing to master. Hopefully this helps me understand branching so I don't
feel like I will break it all again.

------
mamon
The very existence of such guides tells us a lot about how easy to use Git is
:)

~~~
Cthulhu_
Name me any software that doesn't need a guide like this.

like, how do you even exit vim? You need a guide for that. Or to get it closer
to git / this guide, how do you undo / redo?

~~~
oblio
You're comparing git to vim in terms of ease of use...

~~~
SAI_Peregrinus
That's actually a rather good comparison. Both have learning cliffs of
doom[1]but once you've spent a few months with them they're arguably more
powerful than the other options. They're usually fast to use but very hard to
learn. I wouldn't say either one is easy though.

[1]
[https://dementiagaming.files.wordpress.com/2010/08/learning_...](https://dementiagaming.files.wordpress.com/2010/08/learning_curve_of_eve.jpg)

~~~
oblio
That's debatable. I don't think anyone has actually made any study which
proves that git is superior to Mercurial or that vim is superior to Notepad++
or Sublime.

------
teilo
I stubbornly stuck with Mercurial for a long time because of the complexity of
git's UI. But when one moves beyond a few developers, the available tooling
and extensive ecosystem for git makes it inevitable.

~~~
dhimes
Still with hg. You've frightened me.

------
nikanj
We pushed large binaries into our git in the past. This was fine-ish as long
as Git was hosted inhouse, but now that it's SAASed out, they are a huge pain
in the rear.

I've browsed through a few git guides, but can't seem to find anything that
would let me:

1) Do something like "du -s *|sort -n" for the entire Git history

2) Let me "rm -rf --from-history-too", that would cause the remote repo to
actually shrink in size.

~~~
pmjordan
I think you should be able to do something like this with

    
    
      git filter-branch
    

This won't be a terribly fun exercise, and could be very painful if your
history contains a lot of merges. (should be easier with the cactus/rebase
development model)

And of course everyone will have to hard-reset to the new branch.

I should mention I'm far from an expert on this. I've only ever used git
filter branch on a handful of commits, and only based on examples provided by
kind internet people. I certainly haven't done anything nearly as far-reaching
as you're about to embark on.

~~~
Cthulhu_
Yeah, filter-branch is the way to go for this. Also to for example extract a
folder into a new repository. I've used it in a few cases.

------
erikb
I always fight for people really learning git, because that's when it finally
starts to get good. And I always tell people that git is not the tool that
everybody should use. Most people just need a simple data storage with diff
management, like Dropbox or SVN.

But even after nearly 10 years, the pressure from the aint-nobody-got-time-
for-that crowd is still there. I really, really hope that the git devs don't
feel pushed to simplify and therefore depower git. Thinking turning VIM into
the Windows text editor.

~~~
wyuenho
They can certainly provide much better porcelain out of the box. Mercurial is
at least as powerful as git, but I always joked that the learning curve
between the two is something like, you read the docs for 5 mins and you'll
know what the next 50 commands to type into hg. Whereas git, you spend 50
minutes reading the Pro Git book, just so you know what the next 5 commands
should be.

~~~
erikb
Sorry, but you don't know git if you think Mercurial is even coming close.

That is not trolling btw. It's really possible not to know what you can do
with it if you haven't learned it in depth.

The "Git Book" is what you should read. And you read it once, you read it
indepth, and then you're done. After that it's also only 5 minutes of
googling, but you can do a lot more. At that point you can even program a
simplified git if you want.

~~~
wyuenho
TBH, I've been an hg and git user for about 10 years now, I have only come
across simple things that you'd expect to work in git but doesn't. For the
longest time, you have to resort to contortions like this[1] so as to not lose
commits after reverting a merge and then merge again.

[1]:
[https://github.com/git/git/blob/master/Documentation/howto/r...](https://github.com/git/git/blob/master/Documentation/howto/revert-
a-faulty-merge.txt)

What _can 't_ you do in Mercurial that you can in git these days?

BTW, I think we are talking about the same book.

~~~
erikb
I could name a few things, like interactive rebases, but the main thing is not
something that can really be explained. Have you ever significantly become
strong in some kind of contest, may it be sports, gaming, music or similar?
There is this situation where one day you struggle with something and don't
see an end, and the next day it finally clicks, and you can do things
naturally that one day earlier where not even imaginable.

If you've experienced that once consciously, then you can regonize it and you
know when you experience it you've hit someting really good in your life that
moves you forward.

Sadly it seems you must take that hurdle in anything until a certain age or
you will always believe this is impossible and therefore never invest the
energy to reach it.

The thing is that this is not possible to achieve with any random software.
For instance no matter how much you learn MS Word, you probably won't
experience that. But when learning Vim or Emacs there's a chance you get
there. Same is with git. And once you've achieved it once consciously, you
will always want to be in that state in everything important you do.

That's why the really good stuff only has a few followers, most simply don't
get the appeal because they never would invest the energy to get "there" even
if they knew exactly how much it would take. But for those who have achieved
it there is no going back. You cannot go back from controlling (almost) any
bit of your repository to Mercurial.

But that's also why I think for most users something like Mercurial should be
The VCS. Most people don't know the reward they are missing, so they don't
feel the pain of missing it, and therefore have no logical reason to go
through the pain of really learning git.

~~~
Tomis02
Long story short, you're using git because it makes you feel smart.
Ironically, you even admit it - "therefore have no logical reason to go
through the pain of really learning git". Correct, there is no logical reason
to deal with a contorted DVCS when there are better alternatives. Your
arguments are fully subjective.

~~~
erikb
If you tell a blind person, he should use the color red more when dressing, it
might be a good advise, but for the blind person there is no logical reason to
choose red over green.

What I'm saying is that most people are blind when it comes to skill, because
they never make it over the hurdle once. But because most people don't have
any skill, it is general consensus in our society to declare skills based on
interest rather than the ability to solve hard problems or win competitions. I
mean if one person is unable to judge if another person is good at solving
merge conflicts, how could he criticize that person declaring himself as Git
Expert Of The Team. And then again of course most people feel it is
inappropriate to tell other people they are unskilled, so posts like this one
get hated a lot on. But actually it's just calling out the facts. Sky is blue,
grass is green, most people are too unskilled to even recognize what would
enhance skills.

~~~
Tomis02
Unless I'm mistaken, people are paid to solve engineering/programming
problems, not fight with a mess of a DVCS. And if I can use a Mercurial GUI
and do in 15 seconds what would take 5+ minutes in the git command line,
what's the point of being the Git Expert Of The Team? Is version control not
used for saving work progress? A simple thing that 99.99+% of developers
should be taking for granted in an ideal world, just like when pressing Ctrl+S
in your IDE (hopefully) saves the file without asking what encoding you want
to use and what partition you want it written on.

You seem to be under the impression that doing hard things has some intrinsic
value, when it's not the case. You could be rolling rocks uphill all day and
be the best in the world at it. So what? A keyboard going _clickety_ clack*
for 5 minutes while typing git commands (and possibly stackoverflow queries)
is the opposite of work, it's actually a waste of time. Sure, at the end of
the day you solved the problem git presented you; you're smart, and feel
satisfied with you amazing display of intelligence and skill. However, this
ignores the fact that you should not have had to solve that problem to begin
with, because your version control system should just magically work (unless
you get a bonus for each git commit/merge).

> how could he criticize that person declaring himself as Git Expert Of The
> Team

I have no problem with someone being a git expert - I actually will even admit
that I am not a git expert and that there are people extremely skilled at git.
The issue here is that there are some people really skilled at, for example,
typing using the backs of their fingers. Potentially impressive, but entirely
useless. Saying you're skilled at git is like saying you're skilled at using
Jira or editing Wikipedia; good for you, but in all but most extreme cases
this doesn't actually generate value and it also doesn't make you a better
developer.

> one person is unable to judge if another person is good at solving merge
> conflicts

Just out of curiosity, is this somehow relevant to git? Shouldn't solving a
merge conflict be a simple matter of looking at a diff tool presenting you two
inputs and one output screen? Or better yet, wouldn't it be better if you were
automatically told you are editing a file someone else is working on, so that
it prevents conflicts from happening?

~~~
erikb
feel downvoted.

------
0xmohit
A collection of commonly used git tips and tricks:

[https://github.com/git-tips/tips](https://github.com/git-tips/tips)

~~~
0xmohit
Learn git one commit at a time:

[http://gitready.com](http://gitready.com)

------
trevor-e
I think Git would be way more approachable if things were named better. A key
part of Git is whether a file is untracked/unstaged/staged, yet the
terminology around this is very confusing. Why aren't commands simply `git
stage`, `git unstage`, `git add` (to track files), `git remove` (to untrack),
`git undo`, etc? Not to mention the overloaded command names like `git
checkout`, how is `git checkout -- someFile` intuitive at all?

~~~
satish-setty
This is precisely one reason I like Mercurial over Git. Hg has commands which
are more meaningful than those of git.

~~~
dhimes
+1 hg. I see it mentioned so seldom here that I'm actually worried it may go
away.

------
jimmaswell
5+ years later and I still sometimes have to do the classic "repull the entire
repo into a new folder and manually copy the wanted changes over"

------
rootlocus
I think lists like these are part of the problem. You shouldn't rely on tricks
to use git, you should understand how it works.

~~~
migueh
*this

------
yxhuvud

      git checkout name-of-the-correct-branch
      # grab the last commit to master
      git cherry-pick master
      # delete it from master
      git checkout master
      git reset HEAD~ --hard
    

The two lines in the middle can be

    
    
      git cherry-pick -
      git checkout -
    

, and voila, it suddenly is name insensitive.

------
skarap
One can read any amount of similar articles, but if they don't understand the
data model behind all this, git will remain a complex and fragile beast for
them. The feature-set is huge to be able to just remember all possible
commands for all possible scenarios. If you don't know what index is or what a
branch is, this all will look like a bunch of nonsense. On the other hand -
your ruby code won't seem too logical either if you don't know the language.

So if git is the tool you use to get your job done - don't hesitate to spend a
day or 2 on reading how it works and how you're supposed to use it.

------
sirmarksalot
The absolute worst situation I've gotten into was just the other day, when my
team managed to check in two files with the same name, but different
capitalization. The server (Bitbucket) is Linux-based, but all the
workstations are Mac or PC, so the names collided on everyone's desktops. This
prevented anyone from pulling or checking out a different branch, so even
after master was fixed, everyone's environment stayed broken until someone
figured out the right magic incantation (git rm --cached).

~~~
yes_or_gnome
Not really an issue with git, but with OSX. In doing some research of git, I
wanted to look at the first git repos. Those are torvalds/git.git and
torvalds/linux.git. If you clone linux.git on OSX and run `git status`, you'll
see this:

    
    
        $ git status --short
        ## master...origin/master
        M include/uapi/linux/netfilter/xt_connmark.h
        M include/uapi/linux/netfilter/xt_dscp.h
        M include/uapi/linux/netfilter/xt_mark.h
        M include/uapi/linux/netfilter/xt_rateest.h
        M include/uapi/linux/netfilter/xt_tcpmss.h
        M include/uapi/linux/netfilter_ipv4/ipt_ecn.h
        M include/uapi/linux/netfilter_ipv4/ipt_ttl.h
        M include/uapi/linux/netfilter_ipv6/ip6t_hl.h
        M net/netfilter/xt_dscp.c
        M net/netfilter/xt_hl.c
        M net/netfilter/xt_rateest.c
        M net/netfilter/xt_tcpmss.c

~~~
sirmarksalot
I disagree here. Case-insensitive file systems have existed for decades, and
are part of the development landscape. Any tool that works across multiple
machines needs to support them. In this case, I blame Bitbucket, for not
providing any way to treat this as a merge conflict.

~~~
yes_or_gnome
The tool that doesn't work with case insensitive filenames is OSX.

Edit: To add, how is git supposed to handle two files with the same name -- as
is the case -- with a case insensitive file system? You can't have two files
with the "same" name.

    
    
        git checkout file1
    

Is entirely different than

    
    
        git checkout FILE1
    
    

In any other platform ls file1 FILE1 would show two different files, but on
OSX, it'll show the same file twice.

------
lkrubner
I've said this before, but the business leadership, and tech leadership, need
to think carefully about whether or not they need all of the power of Git.
This sums up my concerns:

\-----------------------

 _Here are some minor failure modes I’ve seen with Git:

1\. a branch that stays open for many months, perhaps even a year (for
instance, at Maternity Neighborhood)

2\. data is erased for good because someone makes a mistake while using rebase

3\. a developer introduces a new bug while trying to resolve a merge conflict

4\. widespread but fine-grained cherry picking leaves the team unclear about
what’s been merged and what has not been merged

5\. a developer makes a change in the wrong branch because they forgot what
branch they were in

6\. a developer is unable to recover a stash because they forgot where they
were when they created the stash, or they simply forget that they have work in
a stash

7\. developers confused by working in an unattached commit, after a botched
attempt to revert

8\. a developer feels the need to delete the repo from their harddrive and
clone it again, because the whole repo got into a state that they seemed
unable to resolve

9\. the “blame” command is nearly useless — maybe its because we never know in
which branch a given change was made, finding who made a mistake is very
difficult

10\. developers get confused about which branch will be deployed (I see this
especially in shops that have lots of repos for lots of small apps, and use
different Git workflow strategies for the different repos, often because
different programmers or different teams control the different repos)

11\. developers push their changes to “origin” but forget to push to
“upstream” or vice versa.

But all of that stuff is trivial compared to the major flaw:

Graphic designers, writers, HTML/CSS frontenders, managers, data analysts and
QA staff can’t use Git, even though they all used Subversion._

[http://www.smashcompany.com/business/business-
productivity-h...](http://www.smashcompany.com/business/business-productivity-
has-been-undermined-by-the-hubris-and-power-grabbing-of-elite-computer-
programmers)

~~~
rootlocus
> 2\. data is erased for good because someone makes a mistake while using
> rebase

No. Just no. Please stop spreading FUD like it's candy. Git only deletes
commits after a GC, which won't erase commits from reflog and will keep
unreferenced commits for at least a month before deleting them. And rebasing
generates new commits, leaving the old ones exactly how they were. If somebody
lost a commit after a rebase, and nobody nearby could help them recover it,
they should consider spending a few hours learning about git.

I've been using git for 4 years both at work (with a team of 40+ people) and
at home, without ever having any of the problems listed here (except 3 which
has nothing to do with git). It takes a few hours, maybe a few days to
understand how git works and how to use it. Instead of blaming the tools, you
(and your team) should probably learn how to use them.

~~~
burstmode
>If somebody lost a commit after a rebase, and nobody nearby could help them
recover it, they should consider spending a few hours learning about git.

GIT is the only source control system where you can completly loose commited
data by actions (or commands) available the non-admin user. It's funny to see
that this is considered a "feature" and not a design failure.

~~~
rootlocus
> completly loose commited data

Except the whole point is that you can't completely lose commited data, even
if you tried really hard. And the solution to the problem was `git reflog`
which shows the history of the HEAD.

------
DonnyV
This is why UI's were created. No productive person wants to fill there heads
with a ton of commands and switches when you could just click a button.

~~~
mikestew
Which button? What happens when I click it? Am I going to have to remember
this later?

It’s all “choose your abstraction”, so you’ll be filling your head with
_something_ whether it’s which button to push or what _git checkout_ does. GUI
or not, no button alt text is going to tell you what _rebase_ means.

------
jacobsenscott
Most oh shit git moments are a result of "advanced" git users trying to force
people who just want to get shit done to "keep the history clean" with
rebases. If you stick with git push, pull, and merge you really can't lose
work. And any "advanced" git user knows the right git log incantation to
filter out merge commits and such to make the history look clean.

------
stygiansonic
If this is a guide for beginners, there should be (more?) warnings not to do
history rewriting operations on commits that have already pushed.

~~~
schneidmaster
From the disclaimer at the bottom:

> This site is not intended to be an exhaustive reference, nor is it a
> beginner's tutorial.

~~~
dkarl
It may not be intended to be a beginner's tutorial, but it is. Someone who
needs to be told about `git commit --amend` and `git diff --staged` also needs
to be warned about rewriting history that has been shared with others.

------
aeorgnoieang
I too felt this way once, and I still have to think (or even lookup) about
what the conventions are occasionally, but there really is a point in learning
Git at which you realize there really are not many 'oh shit' situations in
which you can find yourself and not be able to escape unscathed.

But beyond learning Git itself, you need to develop suitable _habits_ for
using Git that are appropriate for your development workflow.

One habit I've consciously developed is to use 'WIP' commits (i.e. a regular
commit with "WIP: Rebase me!" on the first line of the commit message) instead
of stashing. All too often a stash lives for much longer than you'd naively
expect and stashes are much harder to work with than commits. Even if the
modifications are applied right away, commits are nearly as easy to 'apply' as
a stash anyways.

------
m6PeelVLsQ8QawN
It happens to everyone :)

I'd like to contribute my list of git booboos:
[https://github.com/1337/yesterday-i-
learned/blob/master/git....](https://github.com/1337/yesterday-i-
learned/blob/master/git.md#booboos)

~~~
lmm
> I used git in the terminal and the diffs/patches/merges/pull requests don't
> turn out right

Your answer there is just doing git pull --rebase by hand. I don't like that
style at all, but if you must do it surely use the command that's designed for
doing it.

> I pushed stupid things onto the remote server

Worth saying you can branch before fixing - that might be a little less
intimidating than "access by commit ID"

> I already made my changes in multiple commits, but the repo owner wants me
> to rebase it to a single commit

Disagree with "you should do it", though that's probably a political question.

~~~
m6PeelVLsQ8QawN
Thanks for the review! I actually wrote that years ago (in frustration). Will
give it a revision when I have time.

I think I would rebase my PR comment history away only if "the repo owner
wants me to rebase it to a single commit". In that case, I'm just doing
whatever the repo wants the repo to be structured.

------
amelius
> Oh shit, I did something terribly wrong, please tell me git has a magic time
> machine!?!

Shouldn't it be easy for Git to remove objects created after a given time, and
then remove all objects that refer to those objects iteratively?

~~~
icebraining
I think that's exactly what it does; the default is two weeks: [https://git-
scm.com/docs/git-gc](https://git-scm.com/docs/git-gc)

------
city41
One thing I do if I'm a little uncertain about my upcoming git actions is just
move to a new branch: git checkout -b tryScaryGitStuff. That way if I ruin the
commits, the original branch is still around as a back up.

------
zellyn
Is it just me or did [http://ohshitgit.com/#accidental-commit-
master](http://ohshitgit.com/#accidental-commit-master) forget to checkout
master before calling reset?

~~~
XaspR8d
It's still on master because `git branch` just creates and doesn't do
checkout.

(Which is why I've almost exclusively switched to `git checkout -b
<newbranch>` for creating. How often do I want to create but not switch to the
branch?)

~~~
mkesper
Git branch is helpful if you just want to make a snapshot before doing
something potentially harmful. If you hose up, just checkout that branch
again.

------
legohead
So I _just_ ran across this one: git diff --staged

I added a file and wanted to diff it, and this command helped! However, I made
some changes in the file, and when I tried this command a second time, the
changes don't show up :\ Only the original file that was added shows up in the
diff. Now what? It's not the end of the world of course, as I can just look at
the file in my editor, but I usually use diffs as a personal code-review
before I commit.

~~~
deathanatos
There's three "versions" of the code at play, if you will:

* the most recent commit

* the staged files

* the working directory

`git commit`, as you might already know, takes "the staged files" and turns it
into a commit, making that the latest commit. `git add` adds a _snapshot_ of a
file in your working directory to the staged files. The important bit here is
that the copy of the file in the staging area is _separate_ from the file in
your working directory. So, if after `git add`ing a file you make more
changes, you will need to `git add` those subsequent changes if you wish to
commit. `git status` will tell you this:

    
    
      » git status
      On branch master
      Changes to be committed:
        (use "git reset HEAD <file>..." to unstage)
      
      	modified:   foo.txt
      
      Changes not staged for commit:
        (use "git add <file>..." to update what will be committed)
        (use "git checkout -- <file>..." to discard changes in working directory)
      
      	modified:   foo.txt
    

"Changes to be committed" is the staged files. "Changes not staged" is stuff
that has been modified, but not `git add`'d. You can see here that I've
changed foo.txt after git adding it; if I want those changes, I need to git
add it again.

I can look at the diffs, too:

    
    
      # diff between the last commit, and the staged files
      # (i.e., what will be committed)
      git diff --staged
      # diff between the staged files and the working directory
      # (unstaged changes)
      git diff
      # diff of all changes since the last commit:
      # (stage+working dir, essentially)
      git diff HEAD
    

That should be all the various combinations.

I find that a lot of newcomers find the staging area weird, and usually ask
some variant of "why would I _not_ want to commit all of the files I've
changed?" The staging area, used effectively, can really help you break out
things into logical chunks of changes that can then be adequately described
with a message in a commit. This can help others later: if your change is a
bug fix, and someone wants to cherry-pick it to production, they might not
want your new feature, or your lint fixes: they want a minimally risky fix. To
that end, the stage/working dir separation acts as a sieve of sorts, letting
the stuff that's "ready to go" get filtered out into a commit.

I want to mention the extremely useful `git add -p`: this command will
interactively prompt you, hunk by hunk, for whether or not you want to stage
that hunk. It will even let you edit the hunks prior to staging. So, for
example, if I run across a spelling error, or a minor bug, I can very quickly
add it (and _just_ it) to the stage w/ `git add -p`, and then commit it, even
if there are other modifications, even in the same file.

~~~
jordigh
> There's three "versions" of the code at play, if you will:

> * the most recent commit

> * the staged files

> * the working directory

This is weird. The staging area is like a commit but not a commit. They're
changes that git is aware of and has a record of but not quite a permanent
record.

Why not just make it a commit? You can always keep editing commits, or throw
them out, or whatever. That's what I do with Mercurial. I write a commit and I
keep adding stuff to it if I think it needs more stuff (or less stuff).

Gregory Szorc has a more extensive analysis of the situation in first
subsection here: [https://gregoryszorc.com/blog/2017/12/11/high-level-
problems...](https://gregoryszorc.com/blog/2017/12/11/high-level-problems-
with-git-and-how-to-fix-them/)

~~~
deathanatos
My best guess is that the commit metadata (particularly, message) is missing.
You could always have it be "(uncommited, staged changes)" though, and that's
probably descriptive enough. (I agree with you on the whole: having the staged
data be a commit makes things conceptually much simpler.)

My other guess is that the "index" (the other name for the staging area) is
also used for conflicts during merges & rebases, and that somehow plays into
the problem of making it an actual commit. (But again, this comes across more
as an excuse than a reason: I don't any viable reason why the staged changes
can't still be an actual commit, and the merge conflict data just stored as a
separate structure.)

That, or the person who added it just didn't think of it, or couldn't do it
due to backwards compatibility.

------
aetherspawn
For me the big thing was learning to 1/ not work on master unless I’m alone
and 2/ commit all my work incrementally

    
    
        git pull —-rebase
    

&

    
    
        git log 
        git rebase -i HEAD~n
    

So basically I want to make sure my work is pushed to remote as a separate
commit before attempting to run any commands except the ones above. But you
can do pretty much anything with the set above.

~~~
humblebee
I generally replace `git pull` with a `git fetch $remote` + `git rebase
$remote/branch-name`. It provides the added benefit that I can easily diff
changes prior to the rebase so that I know what is going into my branch. The
use of the `--rebase` flag isn't bad though and I may start doing that when I
know I will not be doing any diff prior to a rebase.

I also use `git merge-base` quite a bit so that I do not have to count commits
when working with really simple branches.

------
isuckatcoding
A missed opportunity to say gitting instead of getting.

------
WhyNotHugo
Geez, using `git add .` is the worst thing you can do. Never use this.
Tutorials: stop suggesting this. It's just a recipe to getting yourself into a
mess (plus, you should never work so blindly!).

Add individual files, and, if possible, use `git add -p`, which lets you
review each chunk before adding it to the index. Otherwise, diff and add
individual files.

~~~
ninkendo
Hell, even if you want to stage every change, what you really want is `git add
-A`, which stages deletes too (`git add .` ignores any files you've deleted or
renamed, it only stages new files and changes to existing files.)

------
azernik
Note that for fixing rebase mistakes, `git reflog` is not super user-friendly;
each step in the rebase is included, including the ones that did not involve
user intervention.

In those cases, it's better to use `git reflog $BRANCH_NAME`, which has the
additional advantage of not including your switching from one branch to
another.

------
kbenson
I've always found this flowchart[1] wonderful and concise for handling this
problem (that is, how do I fix the problem I've made for myself with git)..

1: [http://justinhileman.info/article/git-
pretty/](http://justinhileman.info/article/git-pretty/)

------
oelmekki
Maybe it's not worth being in there because of how simple it is, but I guess
it would be useful for newcomers:

    
    
        # Oh shit, I've changed 200 files and want to revert to the state of this morning
        $ git add . && git commit # often. Very often.
        $ git reset --hard commit_id

~~~
icebraining
Wait, aren't you committing and immediately orphaning that commit? I think you
should create a new branch or tag before the reset, otherwise how are going to
get it back?

I guess you could rely on the reflog, but I don't think that's good practice.

~~~
oelmekki
lol, no, it's implicit there are many hours between the first command and the
second one :)

It's purely commiting often to easily have checkpoints to revert to, nothing
fancy (yet, incredibly useful).

------
pascalxus
This is a great resource, but I wish the name was different. The oh-shit
reference is a bit too much.

------
randallsquared
Also useful for panicky moments, with handy workflow:
[http://sethrobertson.github.io/GitFixUm/fixup.html](http://sethrobertson.github.io/GitFixUm/fixup.html)

I visit this page every few weeks. :)

------
k_bx
> Fuck this noise, I give up.

PLEASE add a note to check if you have anything interesting in
stashes/branches before doing the rm -rf, I've lost some work so many times
because of the "fuck this noise" approach.

------
Yokohiii
The site should clearly differ between local changes and pushed changes.
Latter usually requires different strategies to recover, depending on repo
policies.

Git golden rule: Never push -f if you don't know what you are doing.

------
styfle
My oh shit moment is that `git add .` doesn't stage deleted files. I almost
always use `git add -A` because that is typically what I meant, especially for
someone coming from another Version Control system.

------
burgerdev
In choose your own adventure style:
[http://sethrobertson.github.io/GitFixUm/fixup.html](http://sethrobertson.github.io/GitFixUm/fixup.html)

------
crispytx
I ran into a situation the other day where the instructions for "Fuck this
noise, I give up" didn't even work! Glad to hear others have found themselves
in similar boats.

------
magoon
Pro tip: -p

Interactive staging, eg git add -p or git checkout -p

You’ll be asked, for each change, if you want to stage it. This helps
tremendously in preventing commits with stray marks, console logs, etc. Try
it!

------
baristaGeek
Thank you so much! These are pretty useful tricks. Just a question: What's the
difference between reflog and using git log to later checkout to a given
commit?

~~~
rootlocus
You almost never checkout to a commit. You checkout to a branch. A branch is a
reference to a commit, and the HEAD is a reference to a branch. The HEAD is
where you are right now. When you make the HEAD point to a specific commit,
you're in a 'detached head' state.

`git log` tells you all the commits that are part of the branch. More
generally, they are the commits who are children of the current commit (the
commit your branch points to).

`git reflog` tells you where your HEAD has been. When you change for branch to
branch, the HEAD moves around. That history is recorded in the reflog. If you
botch a rebase, your HEAD will sit on top of the newly created (and botched)
commits. You can still access your previous commit by looking where the HEAD
was before moving to the new commits made by the rebase.

------
afshinmeh
Last one in particular: [http://ohshitgit.com/#fuck-this-
noise](http://ohshitgit.com/#fuck-this-noise)

------
methodin
A better tool would be a remote repo clone where you have to resolve messed up
situations and only pass if you push a fixed solution :)

------
aaronsnoswell
Haha. There should be an entry there for 'Oh shit - I just pushed our private
keys to the public github repo'.

~~~
yes_or_gnome
Just as an FYI, those will likely live in Github forever. Run `git ls-remote`
where ever you have had this problem. You'll see that there are refs for every
PR in the form `refs/pull/NNNN/head` and `refs/pull/NNNN/merge`; where `NNNN`
is the PR number, `head` is the latest commit and `merge` is the final commit.

If any of those commits with confidential information is reachable from any of
those commits, then they'll never be garbage collected from Github.

------
ursus_bonum
I use git in this particular way, and if you do anything different you are
WRONG AND BAD or you have IMPURE MOTIVES!

------
sigmonsays
Git is easy once you understand it. What are people doing that is so difficult
to understand?

~~~
migueh
Use without understand it

------
anonymousjunior
reminds me of [https://github.com/blog/2019-how-to-undo-almost-anything-
wit...](https://github.com/blog/2019-how-to-undo-almost-anything-with-git)

------
Vel0cityX
Pretty basic stuff (and very few of them), I expected more.

------
mugglelover
Oh shit I give up could instead be `git clean -fdx`

------
cjsuk
I admit to using this at least once a week.

------
btbuildem
In short:

| Oh shit, I do before I think

~~~
Cthulhu_
Yeah that explains a lot of git mishaps - typos, a missed `--`, `master` vs
`origin master` vs `origin/master`, `reset` vs `checkout`, that kinda thing. A
lot of things that can go wrong with subtle mistakes, and a lot of things that
can go wrong thanks to muscle memory.

------
mugglelover
“Oh shit I give up” should perhaps instead be `git clean -fdx`

------
donald_knuth
Nothing about detached heads?

------
tzahola
You mean, _gitting_ yourself out of bad situations? ( ͡° ͜ʖ ͡°)

