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.
I use the git CLI. I do it for one reason. I know exactly what i'm doing on it. I have nothing to prove to anyone, I'm not trying to impress anyone with my "hacker" skillz.
When I've tried GUI's, I'm not 100% sure what's going on under the covers. Sometimes they try to obfuscate things. While I'm probably not the worlds most advanced user, I know enough to know what I want to do, and how to do it. The CLI let's me do it. The GUI get's in my way.
It's not anything inherent to a visual UI though, it's just that most of the UIs that exist are trying to put their own model on top of git, rather than embracing git's model.
The one exception to this I've found is GitUp (mac only, sadly), and it's excellent. It's whole model is, "what operations can I perform on this graph," which is exactly the model git has. It's great.
There are GUIs that are very close to CLI that don't try to reinvent a wheel and instead just map directly to what git does.
The best one, I think, being Magit for Emacs (if you can call that a 'GUI' given you can run it in the terminal).
If you get used to commit things by-line instead of by-file (which is generally highly recommended with git), and also clean up your history/squash things a lot, using git cli gets VERY tedious very fast; I'd rather do it in several keypresses because why not.
You might want to try Sourcetree if you haven't already. I felt the same way about Git GUIs for a long time, but Sourcetree actually does a good job of getting out of my way, and has a very nice commit history tree viewer to boot.
I like fugitive - it feels like cli git without having to leave the editor. GAdd adds the currently file/selected lines, GBlame pulls up git blame information the ability to reblame, GStatus show the status with the ability to jump to/stage/unstage files and so on.
Tried Magit for a while but it didn't play nice with evil.
Still hoping for a git repl that just does graph queries/transformations though.
Staging, especially partially staging hunks and lines when doing multiple things at once, is way easier in a GUI when you can scroll around for context and easily undo.
For everything else I prefer the command line, because it's faster and I know exactly what is going to happen. I can do what I need to do, no fighting. If I'm just committing everything, I use the CLI. If it's more complicated I use the GUI to stage and commit, and a CLI to rebase/merge/push.
I use sourcetree, but I would like a console feature that shows me what commands its running. Similar to sequel pro's "console" feature shows the raw sql being run.
This is exactly the same reason I too use CLI. But a word of caution Git Bash on windows has some serious problem(s). I remember, I lost my commit and in reflog it doesn't show up on CLI, however GIT UI showed the same! Not sure what's the issue, but it occurred for me twice.
XCode rolled out a feature that allowed you to do an interactive commit just by click on/off switches. My first use of that feature screwed up the repo by committing the wrong pieces.
No thanks, it’s CLI for me, regardless if the IDE promises git support.
The problem, as I see it, is not with the GUIs, it's with the CLI. Just look at the `reset` command: it does several different things, depending on what switches you give it. How would you represent that in a GUI?
You're entitled to your own opinion of course, but you underestimate the efficiency of the command line, especially when you already have one open for other development tasks.
I use one or more GUIs for visualizing branches, and old branch cleanup, and yes, committing single lines from hunks that can't be split.
However for everything else CLI is fairly close to optimal, including interactive adding/rebasing, and don't want to use whatever shitty editor your tool has in it, I want to use vim with syntax highlighting so I can properly format my commit messages. Even something as simple as viewing a full commit is faster in the CLI because you can just pipe it to less or send it to an editor versus whatever tradeoffs a GUI has to make to stay performant, make use of screen space, etc.
One last tool is Fugitive. This blows away anything else I've ever seen for interactively traversing history at the line level.
> committing single lines from hunks that can't be split.
Could you elaborate here? Personally I've always been able to commit just the pieces I need via `git add -p`. Never had problems staging a single line before.
Since this is text I should say: I'm not doubting you, I just like to know the limitations of the tools I'm using.
That's interesting. I switched back from emacs to vim (neovim), and fugitive was recommended. it just looked like :commands for the normal git cli... maybe I missed something.
So even though I edit in vim, I jump back to emacs for magit for bigger commits or multiple smaller commits (where I need to see diffs to be sure I capture my changes).
I have desired something as useful in vim, but I didn't think there was anything. I'll take another look at fugitive.
I've become a big fan of Git Extensions. I like that it doesn't try to layer its own agenda over the Git workflow, shows all the console input/output it uses, and warns me when I'm about to do something stupid, but overall I like it for the same 3 reasons that I like most GUIs:
- It's a live dashboard. A GUI gives me live, persistent information organized well on the screen. I appreciate the power of the CLI for accomplishing tasks, but I've never understood how people prefer it when it comes to simply viewing and understanding the state of something. I don't see why I'd want to run a bunch of commands to see stuff scroll by in my format-constrained terminal when I can have a live, all-up view of multiple aspects of a repo all at once, with relevant, context-sensitive commands on whatever I click on.
- It's discoverable. Most of what I've learned about git has been through clicking around in Git Extensions.
- The structure and organization of the UI helps me to understand how git operates. When I open the "Pull" dialog, for example, the way the controls in the UI are grouped and the kinds of controls that are used help me logically understand what "Pull" can do.
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.
I'd like to also point out tig.
"Tig is an ncurses-based text-mode interface for git"
It doesn't have all the bells and whistles of a GUI, but if you need to look at all the branches, and commits to a repository. tig is an excellent tool. tig doesn't issue any commands though, its only a browser, you'll still need to know the CLI. (essentially a ncurses version of gitk)
I'm normally in a ssh session on a remote box where my compile & run cycles happen. tig is curses based, so no X11 needed, filled in a really nice itch of mine.
The Git GUI that ships with git is very good. It also shows how Git thinks (workspace/staging/commit) that most other gui's struggle with (they try to make it look more like a SVN workflow). For diffs and blame I use TortioseGit. I also extensively use the CLI for most branch actions.
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.
I really like Magit, which is a git GUI you can use without leaving Emacs. It handles 90% of my git needs and is very tightly integrated into my IDE (Emacs). I still use some shell commands (like git mv) occasionally but those are simply m-! away.
I use TortiseGit in my personal and work dev environments. It works works well. That being said, I have had to drop to CLI to fix things that were somewhat more hairy.
Or, you know, that is irrelevant when the person using a GUI makes fewer errors than those who aren't (which has broadly been my experience as well).
Even someone who perfectly understands git can make a typo or have a brain-fart of a day. A GUI significantly reduces the chances of something like that for all users.
Sometimes dev obsession with tool purity does more damage than good.
A well made GUI conveys those semantics more clearly than the default command line interface. Automation is easier from the CLI, but I wouldn't be surprised if a GUI turned out to be best for manual interactions.
Doesn't really make the interface any less crap; though I've yet to see a GUI that didn't shell out to the command-line interface (which almost always makes them very unreliable).
Yeah, I would guess that the parent commenter has a heavily graphical workflow based out of a big honking IDE like IntelliJ. For people doing development in a console anyway, it would take more time to start a git GUI and wait for it to launch than to be done committing and pushing from the CLI.
> I think anyone who uses the CLI is either trying too hard or hasn't realized the beauty of a git GUI.
Nah, it’s just a lot easier than you make it out to be. GUIs are fine too, but if you read the documentation and don’t just memorize a fixed set of commands there’s nothing dangerous, slow, or inconvenient in going about a standard workflow using the CLI.
And yes, lots of people don’t have time for this. Totally okay. Don’t generalize to “anyone who uses the CLI is trying too hard”.
My biggest issue with a GUI is that most that I've seen introduce new terms for various stuff, e.g. "sync" in VS Code, or "revert commit" (in Source Tree maybe?) — there's no Git command called "sync" or "revert", so I'm not immediately sure what they do.
In a CLI I know exactly what's happening.
That's just my opinion though. If people feel comfortable working in a GUI all the more power to them.
I work with a lot of people who have no idea how git actually works and it is infuriating. They all use the git desktop program, and almost every time I get called over to help, it’s because they didn’t sync or refresh or whatever the hell it does.
If you don’t have a good mental model for git, you’re gonna have a bad time.
I don't trust GUI clients; it's easy to not be able to discern the current status, easy to just commit all changes, some of the clients don't respect the pre-push hook, and I've seen other colleagues who have no clue what they're actually doing end up mixing pull and pull --rebase, somehow managing to make duplicate commits with slightly different contents and not having a clue what's going on.
Don't use clients if you don't even understand the basic git workflows. And those usually don't support the advanced oh shit situations this article is about.
> it's easy to not be able to discern the current status
Probably a failure of whatever UI you're using. I manage just fine.
The common statement from CLI types is that "it's just whatever you're better at using" which is true conceptually, but practically, again, CLI users make more mistakes either from fat fingers or lack of understanding of git.
Understanding git conceptually from a UI point of view is easy. You don't even have to have a full understanding of git to be effective at using it, if the UI is good. I'm shit with the git CLI, but I understand what git is doing.
Yes it's easy to do dumb shit in a GUI, the same is true for CLI. In fact, it's less likely that there'd be a button for doing something dumb than it is that a git novice would find some command on StackOverflow and attempt to use it without fully understanding the ramifications of it.
I've felt a good GUI would make using git far more intuitive, but I've yet to find a good one. They all seem to fail on one front or another (too hard to use, don't expose enough functionality, attempt to enforce one workflow, aren't available on platforms I want, are slow/resource hogs).
Usually I use the included gitk to view the repo, and the CLI to manipulate it.
For the most part using git is like five commands and it is definitely fast to use them from the command line if you have some sort of git understanding
Which do you use? I'm generally pro-GUI (I love Postman, for instance, and don't use curl much) but my experience with git GUIs has been that they were kind of half-baked and will not do what I expected, leaving me with a difficult-to-understand mess to clean up.
> I think anyone who uses the CLI is either trying too hard or hasn't realized the beauty of a git GUI.
I've suffered a lot of git GUI bugs. The admittedly large repositories I sometimes deal with cause things to hang and stall, breaking my flow. I keep filing bug reports - truncated diffs because new files were "too large" (presumably someone trying to fix the hang and stall issue), a client that only renders the top half of the window consistently when on a portrait 4K monitor, etc.
The git CLI is simply second nature enough to me at this point that waiting for a GUI to load, refresh, etc. is rarely faster. It does happen, but it's not the common case. Getting a good summary of a set of changes is sometimes one of them. Picking individual hunks/lines is sometimes another - although I prefer to commit with such frequency when using git, that it's extremely rare I have changes that belong in different commits.
Then, looking at perforce, I'm finding more and more cases where I'm dropping out of P4V and into command line tools. Any kind of mass move/edit seems easier to do through the command line. Command line diffs were way easier to review than P4V's file based diff interface when I had changes involving 1 or 2 line tweaks spread across dozens to hundreds of files (such as verifying function rename changelists didn't accidentally pick up other changes.)
I think anyone who's swayed by the beauty of a git GUI has much more patience than me.
"Sourcetree (Not Responding)" - I typed this out while waiting for my Visual Rust tab to focus. Euhg.
I could've made a commit from the command line in that amount of time.
I've tried out a few different GIT GUIs, and never really took to any of them. Settled for using the CLI + many BASH aliases. Anything I do frequently gets a concise alias to minimize typing. I have relatively short fingers, and I'm admittedly a pretty poor typist, so I really emphasize the concise part. Pretty much all the aliases are write only code. I do this for pretty much every other complex CLI application too, e.g., Docker, Heroku, AWS. A little abstraction really speeds up using the CLI. Aliases are my favorite feature of BASH, I think they've saved me literally months of typing at this point in my life.
Here's a few handy ones:
alias currentbranch='git rev-parse --abbrev-ref HEAD'
alias gpush='git push origin $(currentbranch)'
alias gsync='git pull origin $(currentbranch)'
alias ga='git add -A'
alias gc='git checkout'
alias gcm='git commit -m'
alias gca='git commit --amend'
# and my personal favorite (list recent branches)
alias gb='git for-each-ref --sort=-committerdate refs/heads/ --format="%(HEAD) %(color:yellow)%(refname:short)%(color:reset)" | head -n 20'
I use a git GUI for staging commits, but the CLI + text editor for everything else (and no aliases). The CLI is universal--I can go to another dev's computer and get them out of rebase hell without learning their particular git GUI interface. Knowing the CLI by heart is also useful if you ever have to use git server side through SSH. I have found that the CLI fits into my workflow better than the GUI for everything except staging.
I work very well on a cli. I can do partial adds faster than you and don't had any 'oh shit' moments for a few years.
I do not care if someone is using a gui.
My takeaway:
- If i can use git on an cli, i can use git on any server with an cli. I do need this for when i use git on my ansible maschine or on my home media server or when doing something with build infrastructure (jenkins -> git -> cli)
Past experience with GUI frontends and other sorts of simplifying interfaces for version control tools has left me extremely reluctant to use anything more than git's out-of-the-box command line, despite its execrably wretched, unlearnable inconsistency. When things don't make sense with git, I can at least compare notes with coworkers, or search the web and find many discussions where other people have been similarly confused, and received useful advice. If I'm using some custom frontend interface, on the other hand, there are inevitably going to be situations it doesn't handle where I have to fall back to the command line, which I won't remember anything about because I will not have been using it, nobody else on my team is likely to be familiar with the tools I'm using, and discussions on the web are likely to be scarce. Better to just absorb the ongoing pain of git's terrible interface for day-to-day tasks so that I'm not completely hosed when things inevitably go wrong.
I wouldn't say "anyone" is trying to hard but I have seen a lot of people who immediately disregard guis as soon as they internalize that the cli is more difficult. Reasons include wanting to be "badass" or "smart". Yet many also do not care about how got differs and basically ask "how do I save" and proceed to revolve their entire workflow on a few copy pasted or memorized commands.other they hear how "rebase" is only for "smart" people...
On the opposite side gui users can often be unaware of the actual model and instead be working with imperfect internal models with be GUI being a crutch.
In both cases there is lack of desire to learn but I'm often more sympathetic to the latter where people want just enough information to do their work well as oppossed to the former who often make things harder than they have to be in all areas and have lost touch with true expertise in favor of appearance of expertise.
The GUI is said to be a major leap forward in human conputer usage, in the context the CLI just strikes me as either (elitist?) jargon, or brogrammer bravado. In either case, not really a step forward but certain macho. I still don't get it.
I use https://github.com/jonas/tig for interactive staging and git CLI for everything else. Best of both worlds and I don't have to leave the terminal.
+1, not having to use a mouse is great. I also use zsh's inbuilt git aliases [0] which I can't recommend enough -- I've found using git CLI without them a pain now that I'm used to them. These together have me productive and happy.
I use both - to me the big advantage of getting used to GIT CLI is that you learn the tools to handle uncommon operations and automate tasks, which the GUI doesn't give you. When you need to start piping stuff through grep, for example.
In addition to better staging and committing, I love my git GUI for allowing me to easily see and work with every past commit.
Right click on any commit and I can create a new branch there, copy the SHA, do a mixed reset to that location, rebase on it, etc. SO much easier to visualize the actual tree of commits you're working with.
I'm sure some people do do all that from the command line. But every CLI coworker of mine has really only known the basics of branching and committing. The GUI unlocks the repo and all of its branches and commits as something you can play with and explore.
Git is, imo, way too simple to require a gui. How long is it taking you and your coworkers to make commits? git commit -am "message" (or add the files you want with git add, then commit); git push; git pr -m "message". The longest part of that is coming up with a good commit message. A gui isn't going to stop people from making mistakes because the mistakes aren't from complexity of the command line, they are from committing things you shouldn't, which will happen regardless of whether or not you use a gui.
For me, using a GUI makes it much less likely I'll commit the wrong changes as I can quickly review each staged file across the entire tree before committing, and also see if there are unstaged changes (including new files which was often the bane of an SVN workflow) which need to be included.
I typically use git gui to commit changes, the cli for other operations, and occasionally source tree to visualize branches and compare with remote repos.
"- It's easy to keep files uncommitted for long periods of time intentionally, without slowing down my workflow."
"- My commit time is usually much faster than coworkers, with higher accuracy (less frequent accidental commits, etc.)"
Do you mean that as "not committed", or "not pushed"?
If you mean not committed, then why is it a good thing? You should be committing often. Then you push after you are satisfied. It is much easier to revert mistakes that way.
Once upon a time I found a git GUI that I liked (SourceTree). Then Atlassian bought it and pushed their cloud nonsense on me so hard that I just gave up and reverted back to the command line. Eventually I bought the O'Reilly book and figured out how to do the neat things that SourceTree would let me do. Only this time the GUI wouldn't get borked while trying to stage individual lines.
I haven't looked back because I haven't found the need.
I'd consider myself an expert on Git, and I use a GUI of sorts for the vast majority of my Git work: Magit in Emacs.
It has many of the advantages that you describe; makes it easier to get an overview of what's going on, makes it easier to stage individual files, folder, lines of code, hunks, etc.
There are a couple of cases in which I need to fall back to the Git command line, but it's not very often, and I do find it substantially improves my life.
I often see files that clearly shouldn't have been committed. I always bring up using Sourcetree or something else, but everyone seems to think that it's okay the way it is. I can't force it on them and to each their own. It is really frustrating though, because there's this stigma against using a git GUI, but the end results of using one are (in my experience) significantly better.
I don't know how much difference does it make using gui or cli. When i was interviwed for my first job i was asked questions on git. And they asked if i use gui or cli.I think they wanted to know if i really know how to use git through cli. I never used gui for git, maybe i will use in the future. I think Ohsitgit is a good resource which i was trying to find on internet for so long.
It doesn't have to be an exclusive or. I use the CLI for most things, but a GUI when it makes sense (like you mentioned, staging specific hunks). I find that for the most part, my CLI workflow is so straightforward I rarely get in an "oh shit" moment: git pull, git co -b featurebranch, a series of git ci -av, and a git push to open a pull request.
Seriously though, I'm somewhat new to git and any problem I come across (which are many as a new learner) are solved with command line options. I'm not even familiar with the best GUI options out there and have been trying to learn what seemed to be the "standard" way of git'ing.
I’m a big fan of Gitkraken. Great for doing common actions in one click, and graphically viewing history. It’s crazy how negatively people judge me for using it though. It’s like telling someone I prefer Microsoft Word as my IDE.
On mac I can recommend Gitup. It's fast and easy. Also vs code has quite nice git integration. I just use it for making commits though. Everything else is faster from CLI.
I always do `git add --patch`, it's very precise and I can edit lines before staging them. I really don't see why someone would work without it (or a GUI).
The problem of course is the question - What gives anyone a right to do anything? What gives you the right to police the comments? What gives me the right to question your questioning? Meta-discussions always get sidetracked..
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.
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.
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.
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.
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.
I like this. I was trying to do something similar with my Git cheatsheet - https://gist.github.com/JamesSkemp/15fcf0147cb85bb633bf - but it doesn't have the kind of organization I'd like due to the limitations of using a Gist.
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.
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!
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.
I recently had one of those holy-crap-what-did-I-just-do-I-lost-everything moments... But then realized that my scrollback had a list of files and my IDEs (PhpStorm and WebStorm) both kept _local_ revision histories and I was able to restore everything I had done.
I've had a few cases where I accidentally removed a local change before committing it; using Time Machine you can still recover some files then. I wish more editors had built-in support for it, if you're trying to restore a local file, macOS's TextEdit has support for Time Machine.
I accidently screwed up a rebase and dropped a test file. It managed to get merged as a blank file (always review after rebase!), I noticed a few days later when a PR was passing which I swore would of failed some tests I had written. Since then I couldn't exactly remember when I made the commit to the file, so trying to search through reflog became difficult. The above command makes it pretty easy as it will show you every change made to a file.
The user interface should allow you to do anything you want, but warn you properly. In my experience, this is what git does if you’re about to do something dangerous.
How can you blame git for deleting stuff if you blindly pass --force to it?
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.)
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`.
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.
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.
The SVN and P4 articles exists (just google for "svn mistakes" and "perforce p4 mistakes"), but either 1. nobody is sharing them to HN or 2. they do and nobody cares to vote them up.
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.
I recently did something like that—I think I did a reset of the repo and lost all of my changes. Was able to piece it back together using local history. Took me another 20 minutes, but at least all of my data was there.
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.
Glad you figured it out! Having that much work on a single branch is a process smell in itself, ideally you would have found a way to get that code into the repo before it became that large (break down the work into smaller chunks, hide behind feature flags if needed, etc.). Beyond what you just described, reviewing that much work is nearly impossible to do correctly.
At the very least, if you are going to have a long lived branch, make granular commits and push to a remote repo frequently. That will give you a distributed backup strategy.
Ya I realize this now. I usually keep backups. I don't know why I haven't been on this project. I'm using git properly now with proper backups for the project. Though everything's still on the local machine, it's better than the setup I had. I chose to take it as a warning to sort that shit out.
Before doing anything with git that you're unsure of and could have dire consequences, just clone the directory beforehand. Then run the git commands to your heart's content.
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.
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).
That's where tools like github and gitlab come in (or a pre-receive hook on the server), which can deny all commits to master. If that's something you want to prevent of course - and tbf, as soon as there's more than one or two people working on a project, I'd lock master down.
I don't see how that's easier. There's `git checkout -b my-new-branch` which is even easier than the originally proposed solution. Followed by `git checkout master && git reset --hard @{u}` or, if you don't want to switch between branches, `git branch -f master master@{u}`.
I agree that the proposed solution is not the best. If you can fix your problem without dirtying the working tree (i.e. by simply moving changesets around), that's almost always a nicer way to do it.
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.
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.
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.
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.
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.
Early in the history of a repository, I committed some files with sensitive information. The only way to fix this (and similar problems) is to reconstruct the repos starting from the commit just before you committed the unwanted file(s).
I'm a bit of a git naif, there are doubtless better ways to do this. This was mine:
0. Back up my repo.
1. Save the entire commit history as patch files.
2. Use BFG (amazing tool) to scrub all references to the unwanted files [0]
3. Create new repo from the commit just before unwanted files.
4. Apply the patches.
5. Use a custom Perl script to apply the dates in the patch files to the new history. [1]
Technically, your repo will be fully reconstructed at step 4. Also, be advised the patch files themselves may have to be massaged to remove references to the file(s) in question. If the filenames themselves are not unwanted, you can add them to .gitignore for good measure.
Step 5 merely preserves the dates of the original commits. Keep in mind that for this last step, your script will have to work in reverse chronological order as the history will be altered from that point forward.
The BFG program in this guide [0] seems reasonably close to #2. I don't know if you would need to manually trigger garbage collection in the remote repo, or how you'd do that.
Git bfg should do the job, it works well for that and to remove files with secrets... or really anything you want to pretend never existed in your repo :)
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.
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.
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.
I don't think git will lose features, and even if they do, git's core and data model is really, really good - if you look closely, most commands are relatively simple operations on the relatively simple data model and tree structure. I'd say they'll continue the current direction, mostly adding missing features and changing the defaults to be more sane (like default push mechanics).
Creating a sane and consistent UI for “git” is not the same as limiting its power.
They could have had every feature they do today without creating weird differences in options and terminology between sub-commands, and they could have set better defaults.
There needs to be an official “git 3” rethinking of options and defaults to solidify the foundation for the years to come and promote widespread adoption. Anything that simply tries to improve “git” as a layer on top will fail due to obscurity.
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?
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
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.
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).
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
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.
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.
> 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.
>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.
"Instead of blaming the tools, you (and your team) should probably learn how to use them."
From the essay:
--------------------
And Git is intimidating, not just to non-technical staff, but also to inexperienced programmers. In How To Destroy A Tech Startup In Three Easy Steps I talk about Sital, and his unwillingness to commit things to Git. He was learning a great deal about many other technologies, and he didn’t have any spare energy to learn about Git. He went a month without making a commit, and then he only did so because I insisted. After I put a lot of pressure on him, he got to the point where he would make one commit a day, at night, when he was stopping for the day. He would commit to the master branch, because he was confused how to handle different branches. When there was a merge conflict, I would resolve it for him. We worked together for 6 months, and in that time he learned a great deal about a lot of important topics, but he never really learned how to use Git, because it was a low priority, for both him and our CEO.
"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."
It is frustrating that you continue to take your advanced skills for granted. It is frustrating that you can not see what should be an obvious fact: that your skills are above average and therefore it is a mathematical fact that most people have less skill than you, and their lack of skill is a real world business situation that needs to be dealt with realistically. And more so, for the rest of your career your skills will continue to develop, so the gap between you and the average will continue to grow, and therefore the damage that you can do will continue to grow, if you fail to recognize that you are above average.
I can assure that I've seen data lost forever because of "git rebase". It doesn't matter that someone with your skills could have saved the situation. You were not there, therefore your skills don't matter! It is very important that you see this, or you will never be able to give accurate advice to business leaders.
If the leadership of a company decided to hire people with a skill level of x, then they should not also use a technology that requires a skill level of x + 1. You can reasonably tell them "For what you are trying to do, you should hire people with a skill level of x + 1." That is exactly what I did in the situation that I describe here:
But sometimes the business leadership will disagree with you. They may have terrible reasons, but if you can not get them to change their minds, then you need to deal with the consequences of their bad decisions. At which point it makes sense to advocate for a technology that only requires a skill level of x.
[ EDIT TO ADD ]
I'll point out that you are demonstrating a classic case of the Dunning–Kruger effect. In particular:
"the miscalibration of the highly competent stems from an error about others."
That is, you have above average IQ and skill, therefore you perceive things to be easy, which are in fact not easy for the average.
You are an elite programmer. Try to avoid acting like the kind elite programmer that I criticized in "Business productivity has been undermined by the hubris and power-grabbing of elite computer programmers".
Great list. You'll face a predictable backlash by git fanatics, but the fact remains that git's surface area / complexity is way beyond the needs or wants of non-technical users. This is another good rebuttal to the supposed shortcomings of svn which make git necessary:
You're right about the joy that end users feel when they learn TortoiseSVN and are able to put what they see as "infinite undo" into practice so easily.
There was a sarcastic list of git koans, too, somewhere, which I found funny.
Almost everything on that list is wrong, but if I point something out (because I actually learned how it works), I'm just a predictable git fanatic? How is that different from burying your head in the sand?
Most of these have nothing to do with git, but are true of any distributed repository. At that point, your argument becomes: distributed repositories are bad for business.
Then there's this:
> Graphic designers, writers, HTML/CSS frontenders, managers, data analysts and QA staff can’t use Git, even though they all used Subversion.
What rubbish. The features of subversion are a subset of git, and the git equivalents are easy to learn. For a svn user, there's literally only a single additional command they need to know: git push.
To be fair, git is the first VCS I've ever used where there was any real learning curve at all for normal, everyday use. I don't recall anyone ever really teaching me subversion, outside of maybe 5 minutes walking through the GUI. With git I feel like it probably took a few months of regular use before I felt comfortable with it.
That doesn't mean that I'd go back to subversion, but I don't think it's fair to say it's as easy to use.
I'm not necessarily the biggest git fan in the world, but here's some refutations to some of these concerns:
> 1. a branch that stays open for many months, perhaps even a year (for instance, at Maternity Neighborhood)
This is more of a workflow question than a VCS question, and would be true of any VCS that allows branching (i.e. anything remotely close to a modern VCS)
> 2. data is erased for good because someone makes a mistake while using rebase
Data isn't permanently removed from rebasing, you can still get at it with the reflog. If you discovered the problem months later, I suppose that could happen. checkout and reset --hard can irrecobably destroy uncomitted data (as can clean, but that's more obvious and has appropriate guardrails)
> 4. widespread but fine-grained cherry picking leaves the team unclear about what’s been merged and what has not been merged
Overuse of cherry-picking feels like a workflow smell to me, but even still, you shouldn't need to care. Merging the entire branch will work fine if some of the contents have been cherry-picked previously.
> 5. a developer makes a change in the wrong branch because they forgot what branch they were in
True of any VCS with branching.
> 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
I'll agree with you here, I think stash is a bit of a footgun and almost never makes sense to use if the stashed contents are going to live for longer than a minute or two. But this is easily addressable with workflow, don't use stash for anything other than an extremely temporary holding place.
> 7. developers confused by working in an unattached commit, after a botched attempt to revert
Git is generally not great about warning you about dangerous operations or things you shouldn't be doing. Running against a detached HEAD is not one of those things, you'd have to be willfully ignoring what it's telling you to not realize that this isn't a safe thing to do.
> 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
I will agree that git could make it easier to say "just get me back to origin, i give up"
> 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
Blame isn't great, but it sucks in precisely the same way it sucks in any VCS. Just seeing who last committed a line often isn't enough information. It would be cool to see an alternative here, but I don't see many better alternatives around.
It sounds like in general, this is more a concern with dealing with branches and branching, which is totally fair. If simple trunk-based development works for you, branches are an unnecessary addition. But there's no reason you have to use all these git features. You can happily have everyone just work against master and never need to think about branches (in that mode the various Git GUIs will probably be more than adequate as well).
I do agree that git tutorials tend to focus on a more advanced branching / rebase focused workflow, and that simpler resources for less technically minded folks would be handy.
* there's no reason you have to use all these git features *
If you are not using all of the Git features, then why use Git? Why not use something simple, like Subversion? As I wrote in the linked essay:
-------------------
When I list these complaints for developers, most of them respond “You are complaining about Git’s power. The stuff you list isn’t really a flaw, rather those are all examples of how amazing Git is. It is flexible enough that you can do almost anything with it.”
I agree, Git is amazing and very powerful. What I’m suggesting is that we should recognize that it has a very high cost. It might empower complex workflows for sophisticated teams of experienced computer programmers, but it exiles the rest of the staff, and this has significant productivity costs. And Git is intimidating, not just to non-technical staff, but also to inexperienced programmers. In How To Destroy A Tech Startup In Three Easy Steps I talk about Sital, and his unwillingness to commit things to Git. He was learning a great deal about many other technologies, and he didn’t have any spare energy to learn about Git. He went a month without making a commit, and then he only did so because I insisted. After I put a lot of pressure on him, he got to the point where he would make one commit a day, at night, when he was stopping for the day. He would commit to the master branch, because he was confused how to handle different branches. When there was a merge conflict, I would resolve it for him. We worked together for 6 months, and in that time he learned a great deal about a lot of important topics, but he never really learned how to use Git, because it was a low priority, for both him and our CEO.
Git is very powerful? I’m willing to go along with that line of thought so long as we all understand that using a tool that is more powerful than needed can lead to problems.
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.
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.
> Disclaimer: I am not, nor do I even remotely claim to be, an expert at git. This site is not intended to be an exhaustive reference, nor is it a beginner's tutorial. And yes, there are other ways to do these same things with more theoretical purity or whatever, but I've come to these steps through trial and error and lots of swearing and table flipping, and I had this crazy idea to share them with a healthy dose of levity and profanity. Take it or leave it as you will!
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.
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.
> 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.
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.
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.
Creating a branch doesn't check it out by default. To do both at once, it's either "checkout -b" or "branch -c", I forget which because it's "b c" in Magit.
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?)
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.
Yes, this is another one that confuses developers. When you 'git add' a file, it's added to the staging area as it was at that time. If you make subsequent modifications after you've staged it, those are unstaged changes. And you can diff between them. So despite git add'ing a new file, you still have to 'git add' afterwards if you make changes to it.
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.
> 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).
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.
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.
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.
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.)
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.
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)..
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
I think this is bad advice for git newbies two reasons:
1. ‘git add .’ is dangerous and should be avoided IMO, in case you ever have files around that you don’t want to commit. I frequently do. It’s better to ‘git commit -a’, and to just remember to run ‘git status’ frequently and ‘git add’ any new files.
2. ‘git reset —-hard’ is dangerous as well for newbies, since it’s destructive. Better to ‘git revert’ or to ‘git checkout <sha>; git checkout -b <newbranch>’, such that you can always get back to where you were.
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.
git reset --hard for what!? If you are a newcomer making mistakes it is fine for the mistake to be in the commits. Just fix the problem and commit again.
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.
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.
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.
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.
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?
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.
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.
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.
By and large, git is easy to use. Most people will do little beyond committing changes and very occasional branching and merging with the likelihood of not needing any of the tips in the site posted.
For these users, git is perfectly useable and easy to use.
First of all, using git is not really a choice in many companies (except "choose to use git or choose to find another job"). Because, despite being a terrible tool, "git won". So people like me choose to put the minimum of time in getting familiar with a tool that even some git experts/devs admit is confusing to use (after having used it and being intimately familiar with it for years! or maybe you think they were unwilling to spend enough time learning).
More importantly, git (or any DVCS) is NOT work. Lots of technical people seem to have forgotten what purpose versioning control serves (saving your progress as you go) and instead seem to relish in solving git problems that make them feel they're working but add in fact no value whatsoever. That is the core issue. Takes about 10 minutes to get familiar with hg (and then just use a GUI), whereas you have to spend days/weeks reading git docs in order to internalize how it actually works. For what? Just to save some files on a server. I'm sorry, but no.
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.
I use the git CLI. I do it for one reason. I know exactly what i'm doing on it. I have nothing to prove to anyone, I'm not trying to impress anyone with my "hacker" skillz.
When I've tried GUI's, I'm not 100% sure what's going on under the covers. Sometimes they try to obfuscate things. While I'm probably not the worlds most advanced user, I know enough to know what I want to do, and how to do it. The CLI let's me do it. The GUI get's in my way.
It's not anything inherent to a visual UI though, it's just that most of the UIs that exist are trying to put their own model on top of git, rather than embracing git's model.
The one exception to this I've found is GitUp (mac only, sadly), and it's excellent. It's whole model is, "what operations can I perform on this graph," which is exactly the model git has. It's great.
36 replies →
There are GUIs that are very close to CLI that don't try to reinvent a wheel and instead just map directly to what git does.
The best one, I think, being Magit for Emacs (if you can call that a 'GUI' given you can run it in the terminal).
If you get used to commit things by-line instead of by-file (which is generally highly recommended with git), and also clean up your history/squash things a lot, using git cli gets VERY tedious very fast; I'd rather do it in several keypresses because why not.
9 replies →
> I'm not 100% sure what's going on under the covers.
This. A thousand times over. I like to see exactly what git is doing and when; I don't want any magic stuff under the covers done for me.
16 replies →
Same here. Regrettably, if you UNDERSTAND git, a GUI won't work for you. If you're interested in understanding it, it won't work for you either.
A GUI works fine if you want to get things done. If you like to know what goes on under the hood, it's just confuse you.
3 replies →
You might want to try Sourcetree if you haven't already. I felt the same way about Git GUIs for a long time, but Sourcetree actually does a good job of getting out of my way, and has a very nice commit history tree viewer to boot.
6 replies →
I like fugitive - it feels like cli git without having to leave the editor. GAdd adds the currently file/selected lines, GBlame pulls up git blame information the ability to reblame, GStatus show the status with the ability to jump to/stage/unstage files and so on. Tried Magit for a while but it didn't play nice with evil.
Still hoping for a git repl that just does graph queries/transformations though.
I use both.
Staging, especially partially staging hunks and lines when doing multiple things at once, is way easier in a GUI when you can scroll around for context and easily undo.
For everything else I prefer the command line, because it's faster and I know exactly what is going to happen. I can do what I need to do, no fighting. If I'm just committing everything, I use the CLI. If it's more complicated I use the GUI to stage and commit, and a CLI to rebase/merge/push.
I use sourcetree, but I would like a console feature that shows me what commands its running. Similar to sequel pro's "console" feature shows the raw sql being run.
3 replies →
How about if someone made a GUI with a console at the bottom that showed the commands being executed along with results?
1 reply →
This is exactly the same reason I too use CLI. But a word of caution Git Bash on windows has some serious problem(s). I remember, I lost my commit and in reflog it doesn't show up on CLI, however GIT UI showed the same! Not sure what's the issue, but it occurred for me twice.
XCode rolled out a feature that allowed you to do an interactive commit just by click on/off switches. My first use of that feature screwed up the repo by committing the wrong pieces.
No thanks, it’s CLI for me, regardless if the IDE promises git support.
The problem, as I see it, is not with the GUIs, it's with the CLI. Just look at the `reset` command: it does several different things, depending on what switches you give it. How would you represent that in a GUI?
Some git guis log the git commands they execute. Just look at those.
I use either the GUI on Windows or a set of batch files I wrote to automate basic things.
As long as all you're doing is pull, branch, merge and commit, I don't think it matters.
You're entitled to your own opinion of course, but you underestimate the efficiency of the command line, especially when you already have one open for other development tasks.
I use one or more GUIs for visualizing branches, and old branch cleanup, and yes, committing single lines from hunks that can't be split.
However for everything else CLI is fairly close to optimal, including interactive adding/rebasing, and don't want to use whatever shitty editor your tool has in it, I want to use vim with syntax highlighting so I can properly format my commit messages. Even something as simple as viewing a full commit is faster in the CLI because you can just pipe it to less or send it to an editor versus whatever tradeoffs a GUI has to make to stay performant, make use of screen space, etc.
One last tool is Fugitive. This blows away anything else I've ever seen for interactively traversing history at the line level.
> committing single lines from hunks that can't be split.
Could you elaborate here? Personally I've always been able to commit just the pieces I need via `git add -p`. Never had problems staging a single line before.
Since this is text I should say: I'm not doubting you, I just like to know the limitations of the tools I'm using.
13 replies →
That's interesting. I switched back from emacs to vim (neovim), and fugitive was recommended. it just looked like :commands for the normal git cli... maybe I missed something.
So even though I edit in vim, I jump back to emacs for magit for bigger commits or multiple smaller commits (where I need to see diffs to be sure I capture my changes).
I have desired something as useful in vim, but I didn't think there was anything. I'll take another look at fugitive.
3 replies →
> One last tool is Fugitive. This blows away anything else I've ever seen for interactively traversing history at the line level.
Sorry if I'm being think, but how do you do that? Are you talking about Gblame?
1 reply →
I've become a big fan of Git Extensions. I like that it doesn't try to layer its own agenda over the Git workflow, shows all the console input/output it uses, and warns me when I'm about to do something stupid, but overall I like it for the same 3 reasons that I like most GUIs:
- It's a live dashboard. A GUI gives me live, persistent information organized well on the screen. I appreciate the power of the CLI for accomplishing tasks, but I've never understood how people prefer it when it comes to simply viewing and understanding the state of something. I don't see why I'd want to run a bunch of commands to see stuff scroll by in my format-constrained terminal when I can have a live, all-up view of multiple aspects of a repo all at once, with relevant, context-sensitive commands on whatever I click on.
- It's discoverable. Most of what I've learned about git has been through clicking around in Git Extensions.
- The structure and organization of the UI helps me to understand how git operates. When I open the "Pull" dialog, for example, the way the controls in the UI are grouped and the kinds of controls that are used help me logically understand what "Pull" can do.
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.
I'd like to also point out tig. "Tig is an ncurses-based text-mode interface for git"
It doesn't have all the bells and whistles of a GUI, but if you need to look at all the branches, and commits to a repository. tig is an excellent tool. tig doesn't issue any commands though, its only a browser, you'll still need to know the CLI. (essentially a ncurses version of gitk)
I'm normally in a ssh session on a remote box where my compile & run cycles happen. tig is curses based, so no X11 needed, filled in a really nice itch of mine.
[1] https://github.com/jonas/tig
1 reply →
I tested a bunch of Git GUIs. My requisites:
- Open source (and free) - Multiplataform
The one with the best usability was Git Extensions: https://github.com/gitextensions/gitextensions
It is somewhat old ugly, and open a little too much of dialogs, but the workflow really works. It guides you to make the right thing.
A great plus is that it already comes with Kdiff3, a great open source 3 way diff open source program.
1 reply →
The Git GUI that ships with git is very good. It also shows how Git thinks (workspace/staging/commit) that most other gui's struggle with (they try to make it look more like a SVN workflow). For diffs and blame I use TortioseGit. I also extensively use the CLI for most branch actions.
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.
12 replies →
> What GUI do you recommend?
I really like Magit, which is a git GUI you can use without leaving Emacs. It handles 90% of my git needs and is very tightly integrated into my IDE (Emacs). I still use some shell commands (like git mv) occasionally but those are simply m-! away.
1 reply →
Magit in emacs. Probably one of the killer applications for emacs.
8 replies →
I use sourcetree and it's pretty great, especially the aforementioned block-level staging.
Not the OP, but git cola works great for me.
https://git-cola.github.io/
I personally switch between the command line, git gui and gitk. I haven’t yet found a suitable GUI replacement for those two.
I use TortiseGit in my personal and work dev environments. It works works well. That being said, I have had to drop to CLI to fix things that were somewhat more hairy.
2 replies →
I recommend SmartGit; it's not cheap, but it's really, really nice.
1 reply →
SourceTree by Atlassian ... free.
For any Windows users out there, I use GitExtensions, which has served me very well over the years.
I use SmartGit. Way faster and more stable than SourceTree and GitKraken, in my experience.
1 reply →
VSCode or Github Desktop (even if the project is on Gitlab).
Not the OP, but I had come from SourceTree to GitKraken and it's a joy to use.
1 reply →
I like GitKraken
> I think anyone who uses the CLI is either trying too hard or hasn't realized the beauty of a git GUI.
Or, you know, understands and thinks in the semantics of the underlying tool and is already working in other text-based tools.
Or, you know, that is irrelevant when the person using a GUI makes fewer errors than those who aren't (which has broadly been my experience as well).
Even someone who perfectly understands git can make a typo or have a brain-fart of a day. A GUI significantly reduces the chances of something like that for all users.
Sometimes dev obsession with tool purity does more damage than good.
1 reply →
A well made GUI conveys those semantics more clearly than the default command line interface. Automation is easier from the CLI, but I wouldn't be surprised if a GUI turned out to be best for manual interactions.
(Note: I use the CLI almost exclusively.)
Conflict resolution in a GUI with 3 way merge really beats out a command line.
Doesn't really make the interface any less crap; though I've yet to see a GUI that didn't shell out to the command-line interface (which almost always makes them very unreliable).
2 replies →
Yeah, I would guess that the parent commenter has a heavily graphical workflow based out of a big honking IDE like IntelliJ. For people doing development in a console anyway, it would take more time to start a git GUI and wait for it to launch than to be done committing and pushing from the CLI.
1 reply →
> I think anyone who uses the CLI is either trying too hard or hasn't realized the beauty of a git GUI.
Nah, it’s just a lot easier than you make it out to be. GUIs are fine too, but if you read the documentation and don’t just memorize a fixed set of commands there’s nothing dangerous, slow, or inconvenient in going about a standard workflow using the CLI.
And yes, lots of people don’t have time for this. Totally okay. Don’t generalize to “anyone who uses the CLI is trying too hard”.
My biggest issue with a GUI is that most that I've seen introduce new terms for various stuff, e.g. "sync" in VS Code, or "revert commit" (in Source Tree maybe?) — there's no Git command called "sync" or "revert", so I'm not immediately sure what they do.
In a CLI I know exactly what's happening.
That's just my opinion though. If people feel comfortable working in a GUI all the more power to them.
Git does have a revert command.
2 replies →
> no Git command called ... "revert"
Maybe not in the way Source Tree uses it, but there certainly is[1]! I've had to use it a few times.
> git-revert - Revert some existing commits
[1] https://git-scm.com/docs/git-revert
1 reply →
I like Magit because it doesn't try to hide git while still giving all the advantages GP mentioned https://magit.vc/
I work with a lot of people who have no idea how git actually works and it is infuriating. They all use the git desktop program, and almost every time I get called over to help, it’s because they didn’t sync or refresh or whatever the hell it does.
If you don’t have a good mental model for git, you’re gonna have a bad time.
1 reply →
I don't trust GUI clients; it's easy to not be able to discern the current status, easy to just commit all changes, some of the clients don't respect the pre-push hook, and I've seen other colleagues who have no clue what they're actually doing end up mixing pull and pull --rebase, somehow managing to make duplicate commits with slightly different contents and not having a clue what's going on.
Don't use clients if you don't even understand the basic git workflows. And those usually don't support the advanced oh shit situations this article is about.
> it's easy to not be able to discern the current status
Probably a failure of whatever UI you're using. I manage just fine.
The common statement from CLI types is that "it's just whatever you're better at using" which is true conceptually, but practically, again, CLI users make more mistakes either from fat fingers or lack of understanding of git.
Understanding git conceptually from a UI point of view is easy. You don't even have to have a full understanding of git to be effective at using it, if the UI is good. I'm shit with the git CLI, but I understand what git is doing.
Yes it's easy to do dumb shit in a GUI, the same is true for CLI. In fact, it's less likely that there'd be a button for doing something dumb than it is that a git novice would find some command on StackOverflow and attempt to use it without fully understanding the ramifications of it.
I've felt a good GUI would make using git far more intuitive, but I've yet to find a good one. They all seem to fail on one front or another (too hard to use, don't expose enough functionality, attempt to enforce one workflow, aren't available on platforms I want, are slow/resource hogs).
Usually I use the included gitk to view the repo, and the CLI to manipulate it.
For the most part using git is like five commands and it is definitely fast to use them from the command line if you have some sort of git understanding
Which do you use? I'm generally pro-GUI (I love Postman, for instance, and don't use curl much) but my experience with git GUIs has been that they were kind of half-baked and will not do what I expected, leaving me with a difficult-to-understand mess to clean up.
> I think anyone who uses the CLI is either trying too hard or hasn't realized the beauty of a git GUI.
I've suffered a lot of git GUI bugs. The admittedly large repositories I sometimes deal with cause things to hang and stall, breaking my flow. I keep filing bug reports - truncated diffs because new files were "too large" (presumably someone trying to fix the hang and stall issue), a client that only renders the top half of the window consistently when on a portrait 4K monitor, etc.
The git CLI is simply second nature enough to me at this point that waiting for a GUI to load, refresh, etc. is rarely faster. It does happen, but it's not the common case. Getting a good summary of a set of changes is sometimes one of them. Picking individual hunks/lines is sometimes another - although I prefer to commit with such frequency when using git, that it's extremely rare I have changes that belong in different commits.
Then, looking at perforce, I'm finding more and more cases where I'm dropping out of P4V and into command line tools. Any kind of mass move/edit seems easier to do through the command line. Command line diffs were way easier to review than P4V's file based diff interface when I had changes involving 1 or 2 line tweaks spread across dozens to hundreds of files (such as verifying function rename changelists didn't accidentally pick up other changes.)
I think anyone who's swayed by the beauty of a git GUI has much more patience than me.
"Sourcetree (Not Responding)" - I typed this out while waiting for my Visual Rust tab to focus. Euhg.
I could've made a commit from the command line in that amount of time.
I've found my sweet spot is using both a GUI (Github app, to be specific) and a CLI.
GUI for partial commits and reviewing my change, and then command line for basically everything else (merge, checkout, branch, etc).
I've tried out a few different GIT GUIs, and never really took to any of them. Settled for using the CLI + many BASH aliases. Anything I do frequently gets a concise alias to minimize typing. I have relatively short fingers, and I'm admittedly a pretty poor typist, so I really emphasize the concise part. Pretty much all the aliases are write only code. I do this for pretty much every other complex CLI application too, e.g., Docker, Heroku, AWS. A little abstraction really speeds up using the CLI. Aliases are my favorite feature of BASH, I think they've saved me literally months of typing at this point in my life.
Here's a few handy ones:
My version of gsync is `git pull --rebase origin ${currentbranch}`, since I hate having random merge commits.
I use a git GUI for staging commits, but the CLI + text editor for everything else (and no aliases). The CLI is universal--I can go to another dev's computer and get them out of rebase hell without learning their particular git GUI interface. Knowing the CLI by heart is also useful if you ever have to use git server side through SSH. I have found that the CLI fits into my workflow better than the GUI for everything except staging.
I work very well on a cli. I can do partial adds faster than you and don't had any 'oh shit' moments for a few years.
I do not care if someone is using a gui.
My takeaway: - If i can use git on an cli, i can use git on any server with an cli. I do need this for when i use git on my ansible maschine or on my home media server or when doing something with build infrastructure (jenkins -> git -> cli)
Past experience with GUI frontends and other sorts of simplifying interfaces for version control tools has left me extremely reluctant to use anything more than git's out-of-the-box command line, despite its execrably wretched, unlearnable inconsistency. When things don't make sense with git, I can at least compare notes with coworkers, or search the web and find many discussions where other people have been similarly confused, and received useful advice. If I'm using some custom frontend interface, on the other hand, there are inevitably going to be situations it doesn't handle where I have to fall back to the command line, which I won't remember anything about because I will not have been using it, nobody else on my team is likely to be familiar with the tools I'm using, and discussions on the web are likely to be scarce. Better to just absorb the ongoing pain of git's terrible interface for day-to-day tasks so that I'm not completely hosed when things inevitably go wrong.
Additionally you can always use the command line if you need to. I use a GUI for 99% of what I do, then use the CLI for what I need it for.
I wouldn't say "anyone" is trying to hard but I have seen a lot of people who immediately disregard guis as soon as they internalize that the cli is more difficult. Reasons include wanting to be "badass" or "smart". Yet many also do not care about how got differs and basically ask "how do I save" and proceed to revolve their entire workflow on a few copy pasted or memorized commands.other they hear how "rebase" is only for "smart" people...
On the opposite side gui users can often be unaware of the actual model and instead be working with imperfect internal models with be GUI being a crutch.
In both cases there is lack of desire to learn but I'm often more sympathetic to the latter where people want just enough information to do their work well as oppossed to the former who often make things harder than they have to be in all areas and have lost touch with true expertise in favor of appearance of expertise.
Which Git GUI are you using?
The GUI is said to be a major leap forward in human conputer usage, in the context the CLI just strikes me as either (elitist?) jargon, or brogrammer bravado. In either case, not really a step forward but certain macho. I still don't get it.
I use https://github.com/jonas/tig for interactive staging and git CLI for everything else. Best of both worlds and I don't have to leave the terminal.
+1, not having to use a mouse is great. I also use zsh's inbuilt git aliases [0] which I can't recommend enough -- I've found using git CLI without them a pain now that I'm used to them. These together have me productive and happy.
[0] https://github.com/robbyrussell/oh-my-zsh/wiki/Plugin:git
1 reply →
> I think anyone who uses the CLI is either trying too hard or hasn't realized the beauty of a git GUI.
Or just couldn't be bothered with leaving terminal. I refuse to reach for mouse for any repository operation when everything else I do from console.
I use both - to me the big advantage of getting used to GIT CLI is that you learn the tools to handle uncommon operations and automate tasks, which the GUI doesn't give you. When you need to start piping stuff through grep, for example.
GUI user here. Genuine question: when would you need to pipe stuff through grep? I get it would be a rare situation, but I can't think of one.
1 reply →
In addition to better staging and committing, I love my git GUI for allowing me to easily see and work with every past commit.
Right click on any commit and I can create a new branch there, copy the SHA, do a mixed reset to that location, rebase on it, etc. SO much easier to visualize the actual tree of commits you're working with.
I'm sure some people do do all that from the command line. But every CLI coworker of mine has really only known the basics of branching and committing. The GUI unlocks the repo and all of its branches and commits as something you can play with and explore.
Git is, imo, way too simple to require a gui. How long is it taking you and your coworkers to make commits? git commit -am "message" (or add the files you want with git add, then commit); git push; git pr -m "message". The longest part of that is coming up with a good commit message. A gui isn't going to stop people from making mistakes because the mistakes aren't from complexity of the command line, they are from committing things you shouldn't, which will happen regardless of whether or not you use a gui.
For me, using a GUI makes it much less likely I'll commit the wrong changes as I can quickly review each staged file across the entire tree before committing, and also see if there are unstaged changes (including new files which was often the bane of an SVN workflow) which need to be included.
I typically use git gui to commit changes, the cli for other operations, and occasionally source tree to visualize branches and compare with remote repos.
The Git UI that comes with intelij can do all the essentials git statements and has a console that logs everything it is doing.
And you can also learn useful things by reading the console sometimes. There is no magic.
"- It's easy to keep files uncommitted for long periods of time intentionally, without slowing down my workflow." "- My commit time is usually much faster than coworkers, with higher accuracy (less frequent accidental commits, etc.)"
Do you mean that as "not committed", or "not pushed"?
If you mean not committed, then why is it a good thing? You should be committing often. Then you push after you are satisfied. It is much easier to revert mistakes that way.
Once upon a time I found a git GUI that I liked (SourceTree). Then Atlassian bought it and pushed their cloud nonsense on me so hard that I just gave up and reverted back to the command line. Eventually I bought the O'Reilly book and figured out how to do the neat things that SourceTree would let me do. Only this time the GUI wouldn't get borked while trying to stage individual lines.
I haven't looked back because I haven't found the need.
I'd consider myself an expert on Git, and I use a GUI of sorts for the vast majority of my Git work: Magit in Emacs.
It has many of the advantages that you describe; makes it easier to get an overview of what's going on, makes it easier to stage individual files, folder, lines of code, hunks, etc.
There are a couple of cases in which I need to fall back to the Git command line, but it's not very often, and I do find it substantially improves my life.
I'm in such agreement here.
I often see files that clearly shouldn't have been committed. I always bring up using Sourcetree or something else, but everyone seems to think that it's okay the way it is. I can't force it on them and to each their own. It is really frustrating though, because there's this stigma against using a git GUI, but the end results of using one are (in my experience) significantly better.
I don't know how much difference does it make using gui or cli. When i was interviwed for my first job i was asked questions on git. And they asked if i use gui or cli.I think they wanted to know if i really know how to use git through cli. I never used gui for git, maybe i will use in the future. I think Ohsitgit is a good resource which i was trying to find on internet for so long.
It doesn't have to be an exclusive or. I use the CLI for most things, but a GUI when it makes sense (like you mentioned, staging specific hunks). I find that for the most part, my CLI workflow is so straightforward I rarely get in an "oh shit" moment: git pull, git co -b featurebranch, a series of git ci -av, and a git push to open a pull request.
There's a git GUI??
Seriously though, I'm somewhat new to git and any problem I come across (which are many as a new learner) are solved with command line options. I'm not even familiar with the best GUI options out there and have been trying to learn what seemed to be the "standard" way of git'ing.
I’m a big fan of Gitkraken. Great for doing common actions in one click, and graphically viewing history. It’s crazy how negatively people judge me for using it though. It’s like telling someone I prefer Microsoft Word as my IDE.
Seconded for a GUI. I've been using gitkraken for almost a year now, never looked back.
(full disclosure: as of last week I actually work for the company behind gitkraken but I started using it far before I realized they were local)
On mac I can recommend Gitup. It's fast and easy. Also vs code has quite nice git integration. I just use it for making commits though. Everything else is faster from CLI.
Android Studio has a git UI built-in so it's really useful.
I always do `git add --patch`, it's very precise and I can edit lines before staging them. I really don't see why someone would work without it (or a GUI).
I use the CLI because I don't currently work on any group projects.
I’ve only seen the opposite effect in practice. My odd look as well.
So... which git GUI are you using?
Which git GUI are you using?
What git gui? Git kraken?
Which GUI do you use?
> I think anyone who uses the CLI is either trying too hard
Why do you think it's okay to share this opinion?
Because this is a forum and nothing I say matters.
The problem of course is the question - What gives anyone a right to do anything? What gives you the right to police the comments? What gives me the right to question your questioning? Meta-discussions always get sidetracked..
What makes you think it is not?
3 replies →
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.
13 replies →
practicing safe version control is better than abstinence
1 reply →
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.
2 replies →
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.
14 replies →
Nice. For anyone who hasn't see it, Flight Rules for Git is even more comprehensive: https://github.com/k88hudson/git-flight-rules
I like this. I was trying to do something similar with my Git cheatsheet - https://gist.github.com/JamesSkemp/15fcf0147cb85bb633bf - but it doesn't have the kind of organization I'd like due to the limitations of using a Gist.
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.
> I'm planning on making a hard push for git on the team I just joined
You mean a force push. `git push --force` is one of my favorite commands. I've aliased `git yolo` to `git push --force --no-verify`.
5 replies →
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.
10 replies →
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.
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!
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.
11 replies →
Preach on brother!!!!!
Beautifully stated.
I recently had one of those holy-crap-what-did-I-just-do-I-lost-everything moments... But then realized that my scrollback had a list of files and my IDEs (PhpStorm and WebStorm) both kept _local_ revision histories and I was able to restore everything I had done.
I've been saved by the local history in IntelliJ more times than I would like to admit, heh.
I've had a few cases where I accidentally removed a local change before committing it; using Time Machine you can still recover some files then. I wish more editors had built-in support for it, if you're trying to restore a local file, macOS's TextEdit has support for Time Machine.
This combined with Time Machine backups means I haven't lost source in years.
Learning about the reflog just changed everything -- it removes all fear of "loosing" anything but uncommitted work.
In a similar vain to `git checkout`, `git reset --hard` is also an excellent way to loose uncommitted work.
When I know what file I'm missing a commit from, I usually end up using `git log` instead.
I accidently screwed up a rebase and dropped a test file. It managed to get merged as a blank file (always review after rebase!), I noticed a few days later when a PR was passing which I swore would of failed some tests I had written. Since then I couldn't exactly remember when I made the commit to the file, so trying to search through reflog became difficult. The above command makes it pretty easy as it will show you every change made to a file.
I'm a big fan of 'git checkout -p'. Even if you nuke a hunk you actually wanted, it's not actually gone until it falls off your scrollback buffer.
I go all in https://github.com/rroller/dotfiles/blob/master/bin/git-nuke
When in doubt either:
* commit to an itermediate branch as storage
* git stash && git stash apply (repeat last to recover stuff)
git stash pop is often nicer for temporary stuff.
The underlying system is well designed, but a user interface that allows you to get into a point where you can hose a repo is anything but.
The user interface should allow you to do anything you want, but warn you properly. In my experience, this is what git does if you’re about to do something dangerous.
How can you blame git for deleting stuff if you blindly pass --force to it?
you can always get back to what you had before unless you try really, really hard to destroy data
git reflog is your friend
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.)
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`.
Quick quiz, what does 'git checkout x/y' do? I am aware of users hitting at least 3 interpretations.
I'd say it changes your code to match that of a branch in your local copy of the repo.
1 reply →
I think you already answered your own question. It is very hard to get comfortable with things if they are unintuitive :)
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.)
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.
Reminds me of all articles attempting to explain how simple monads are
The SVN and P4 articles exists (just google for "svn mistakes" and "perforce p4 mistakes"), but either 1. nobody is sharing them to HN or 2. they do and nobody cares to vote them up.
Unrelated topic (falling cats), same logical fallacy: http://www.radiolab.org/story/102525-vertigo/ (Starting around 14:20)
“Nobody submits them, or nobody cares to vote them up.”
That should tell you something: these articles don’t resonate with the crowd. That should tell you something.
3 replies →
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.
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.
+ it shows you a diff with the ability to revert individual changes in code
I recently did something like that—I think I did a reset of the repo and lost all of my changes. Was able to piece it back together using local history. Took me another 20 minutes, but at least all of my data was there.
“Git gets easier once you get the basic idea that branches are homeomorphic endofunctors mapping submanifolds of a Hilbert space.”
— Isaac Wolkerstorfer (@agnoster)
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.
Glad you figured it out! Having that much work on a single branch is a process smell in itself, ideally you would have found a way to get that code into the repo before it became that large (break down the work into smaller chunks, hide behind feature flags if needed, etc.). Beyond what you just described, reviewing that much work is nearly impossible to do correctly.
At the very least, if you are going to have a long lived branch, make granular commits and push to a remote repo frequently. That will give you a distributed backup strategy.
Git is not a backup! Had you had one, you could have had your mind at ease.
Ya I realize this now. I usually keep backups. I don't know why I haven't been on this project. I'm using git properly now with proper backups for the project. Though everything's still on the local machine, it's better than the setup I had. I chose to take it as a warning to sort that shit out.
Pushing to a remote is a backup. Gitlab offers private repositories for free.
3 replies →
Before doing anything with git that you're unsure of and could have dire consequences, just clone the directory beforehand. Then run the git commands to your heart's content.
Do yourself a favor and learn git properly. It pays of hugely in the long run. The book that clicked for me was Git Internals [1]
[1] https://github.com/pluralsight/git-internals-pdf
> 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
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.
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).
4 replies →
That's where tools like github and gitlab come in (or a pre-receive hook on the server), which can deny all commits to master. If that's something you want to prevent of course - and tbf, as soon as there's more than one or two people working on a project, I'd lock master down.
I don't see how that's easier. There's `git checkout -b my-new-branch` which is even easier than the originally proposed solution. Followed by `git checkout master && git reset --hard @{u}` or, if you don't want to switch between branches, `git branch -f master master@{u}`.
I agree that the proposed solution is not the best. If you can fix your problem without dirtying the working tree (i.e. by simply moving changesets around), that's almost always a nicer way to do it.
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.
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/
It's a great way to learn without putting your real repository at risk.
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.
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.
Still with hg. You've frightened me.
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.
I think you should be able to do something like this with
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.
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.
Early in the history of a repository, I committed some files with sensitive information. The only way to fix this (and similar problems) is to reconstruct the repos starting from the commit just before you committed the unwanted file(s).
I'm a bit of a git naif, there are doubtless better ways to do this. This was mine:
Technically, your repo will be fully reconstructed at step 4. Also, be advised the patch files themselves may have to be massaged to remove references to the file(s) in question. If the filenames themselves are not unwanted, you can add them to .gitignore for good measure.
Step 5 merely preserves the dates of the original commits. Keep in mind that for this last step, your script will have to work in reverse chronological order as the history will be altered from that point forward.
EDIT: Swap steps 1 and 2. Add advisement that patch files may require manual alteration. Add hint regarding .gitignore. Title case "Perl".
Have you looked at git-filter-branch?
The BFG program in this guide [0] seems reasonably close to #2. I don't know if you would need to manually trigger garbage collection in the remote repo, or how you'd do that.
https://help.github.com/articles/removing-sensitive-data-fro...
You'll be rewriting history via filter-branch, e.g. everyone would need to do the same for the clone and be sure not to push up the old history: https://help.github.com/articles/removing-files-from-a-repos...
For part 1 - I used this https://stackoverflow.com/questions/13403069/how-to-find-out...
Which for part 2 then leads to the BFG repo cleaner (which I haven't used)
Git bfg should do the job, it works well for that and to remove files with secrets... or really anything you want to pretend never existed in your repo :)
https://rtyley.github.io/bfg-repo-cleaner/
Have you tried this:
https://rtyley.github.io/bfg-repo-cleaner/
I've used it in the past, and it's pretty straightforward and does the job well :)
https://help.github.com/articles/removing-sensitive-data-fro...
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.
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.
I am glad hg has both Facebook and Google using it. Otherwise Git would have suck the air out of DVCS.
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.
7 replies →
I don't think git will lose features, and even if they do, git's core and data model is really, really good - if you look closely, most commands are relatively simple operations on the relatively simple data model and tree structure. I'd say they'll continue the current direction, mostly adding missing features and changing the defaults to be more sane (like default push mechanics).
Creating a sane and consistent UI for “git” is not the same as limiting its power.
They could have had every feature they do today without creating weird differences in options and terminology between sub-commands, and they could have set better defaults.
There needs to be an official “git 3” rethinking of options and defaults to solidify the foundation for the years to come and promote widespread adoption. Anything that simply tries to improve “git” as a layer on top will fail due to obscurity.
A collection of commonly used git tips and tricks:
https://github.com/git-tips/tips
Learn git one commit at a time:
http://gitready.com
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?
This is precisely one reason I like Mercurial over Git. Hg has commands which are more meaningful than those of git.
+1 hg. I see it mentioned so seldom here that I'm actually worried it may go away.
Why not `git track` and `git untrack`?
TBH I'm not sure why I left add/remove in, track/untrack is simpler and more in line with what I was saying. :)
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"
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.
*this
The two lines in the middle can be
, and voila, it suddenly is name insensitive.
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.
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).
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:
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.
1 reply →
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...
> 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.
>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.
1 reply →
"Instead of blaming the tools, you (and your team) should probably learn how to use them."
From the essay:
--------------------
And Git is intimidating, not just to non-technical staff, but also to inexperienced programmers. In How To Destroy A Tech Startup In Three Easy Steps I talk about Sital, and his unwillingness to commit things to Git. He was learning a great deal about many other technologies, and he didn’t have any spare energy to learn about Git. He went a month without making a commit, and then he only did so because I insisted. After I put a lot of pressure on him, he got to the point where he would make one commit a day, at night, when he was stopping for the day. He would commit to the master branch, because he was confused how to handle different branches. When there was a merge conflict, I would resolve it for him. We worked together for 6 months, and in that time he learned a great deal about a lot of important topics, but he never really learned how to use Git, because it was a low priority, for both him and our CEO.
10 replies →
About this:
"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."
It is frustrating that you continue to take your advanced skills for granted. It is frustrating that you can not see what should be an obvious fact: that your skills are above average and therefore it is a mathematical fact that most people have less skill than you, and their lack of skill is a real world business situation that needs to be dealt with realistically. And more so, for the rest of your career your skills will continue to develop, so the gap between you and the average will continue to grow, and therefore the damage that you can do will continue to grow, if you fail to recognize that you are above average.
I can assure that I've seen data lost forever because of "git rebase". It doesn't matter that someone with your skills could have saved the situation. You were not there, therefore your skills don't matter! It is very important that you see this, or you will never be able to give accurate advice to business leaders.
If the leadership of a company decided to hire people with a skill level of x, then they should not also use a technology that requires a skill level of x + 1. You can reasonably tell them "For what you are trying to do, you should hire people with a skill level of x + 1." That is exactly what I did in the situation that I describe here:
https://www.amazon.com/Destroy-Tech-Startup-Easy-Steps/dp/09...
But sometimes the business leadership will disagree with you. They may have terrible reasons, but if you can not get them to change their minds, then you need to deal with the consequences of their bad decisions. At which point it makes sense to advocate for a technology that only requires a skill level of x.
[ EDIT TO ADD ]
I'll point out that you are demonstrating a classic case of the Dunning–Kruger effect. In particular:
"the miscalibration of the highly competent stems from an error about others."
That is, you have above average IQ and skill, therefore you perceive things to be easy, which are in fact not easy for the average.
https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect
You are an elite programmer. Try to avoid acting like the kind elite programmer that I criticized in "Business productivity has been undermined by the hubris and power-grabbing of elite computer programmers".
Great list. You'll face a predictable backlash by git fanatics, but the fact remains that git's surface area / complexity is way beyond the needs or wants of non-technical users. This is another good rebuttal to the supposed shortcomings of svn which make git necessary:
https://svnvsgit.com/
You're right about the joy that end users feel when they learn TortoiseSVN and are able to put what they see as "infinite undo" into practice so easily.
There was a sarcastic list of git koans, too, somewhere, which I found funny.
Almost everything on that list is wrong, but if I point something out (because I actually learned how it works), I'm just a predictable git fanatic? How is that different from burying your head in the sand?
3 replies →
Most of these have nothing to do with git, but are true of any distributed repository. At that point, your argument becomes: distributed repositories are bad for business.
Then there's this:
> Graphic designers, writers, HTML/CSS frontenders, managers, data analysts and QA staff can’t use Git, even though they all used Subversion.
What rubbish. The features of subversion are a subset of git, and the git equivalents are easy to learn. For a svn user, there's literally only a single additional command they need to know: git push.
To be fair, git is the first VCS I've ever used where there was any real learning curve at all for normal, everyday use. I don't recall anyone ever really teaching me subversion, outside of maybe 5 minutes walking through the GUI. With git I feel like it probably took a few months of regular use before I felt comfortable with it.
That doesn't mean that I'd go back to subversion, but I don't think it's fair to say it's as easy to use.
2 replies →
The features of subversion are a subset of git
Well, except for locking, which I hear is useful for people working with hard-to-merge files.
distributed repositories are bad for business.
If you read the whole essay, you will see that "distributed repositories are bad for business" is exactly the argument being made.
I'm not necessarily the biggest git fan in the world, but here's some refutations to some of these concerns:
> 1. a branch that stays open for many months, perhaps even a year (for instance, at Maternity Neighborhood)
This is more of a workflow question than a VCS question, and would be true of any VCS that allows branching (i.e. anything remotely close to a modern VCS)
> 2. data is erased for good because someone makes a mistake while using rebase
Data isn't permanently removed from rebasing, you can still get at it with the reflog. If you discovered the problem months later, I suppose that could happen. checkout and reset --hard can irrecobably destroy uncomitted data (as can clean, but that's more obvious and has appropriate guardrails)
> 4. widespread but fine-grained cherry picking leaves the team unclear about what’s been merged and what has not been merged
Overuse of cherry-picking feels like a workflow smell to me, but even still, you shouldn't need to care. Merging the entire branch will work fine if some of the contents have been cherry-picked previously.
> 5. a developer makes a change in the wrong branch because they forgot what branch they were in
True of any VCS with branching.
> 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
I'll agree with you here, I think stash is a bit of a footgun and almost never makes sense to use if the stashed contents are going to live for longer than a minute or two. But this is easily addressable with workflow, don't use stash for anything other than an extremely temporary holding place.
> 7. developers confused by working in an unattached commit, after a botched attempt to revert
Git is generally not great about warning you about dangerous operations or things you shouldn't be doing. Running against a detached HEAD is not one of those things, you'd have to be willfully ignoring what it's telling you to not realize that this isn't a safe thing to do.
> 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
I will agree that git could make it easier to say "just get me back to origin, i give up"
> 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
Blame isn't great, but it sucks in precisely the same way it sucks in any VCS. Just seeing who last committed a line often isn't enough information. It would be cool to see an alternative here, but I don't see many better alternatives around.
It sounds like in general, this is more a concern with dealing with branches and branching, which is totally fair. If simple trunk-based development works for you, branches are an unnecessary addition. But there's no reason you have to use all these git features. You can happily have everyone just work against master and never need to think about branches (in that mode the various Git GUIs will probably be more than adequate as well).
I do agree that git tutorials tend to focus on a more advanced branching / rebase focused workflow, and that simpler resources for less technically minded folks would be handy.
* there's no reason you have to use all these git features *
If you are not using all of the Git features, then why use Git? Why not use something simple, like Subversion? As I wrote in the linked essay:
-------------------
When I list these complaints for developers, most of them respond “You are complaining about Git’s power. The stuff you list isn’t really a flaw, rather those are all examples of how amazing Git is. It is flexible enough that you can do almost anything with it.”
I agree, Git is amazing and very powerful. What I’m suggesting is that we should recognize that it has a very high cost. It might empower complex workflows for sophisticated teams of experienced computer programmers, but it exiles the rest of the staff, and this has significant productivity costs. And Git is intimidating, not just to non-technical staff, but also to inexperienced programmers. In How To Destroy A Tech Startup In Three Easy Steps I talk about Sital, and his unwillingness to commit things to Git. He was learning a great deal about many other technologies, and he didn’t have any spare energy to learn about Git. He went a month without making a commit, and then he only did so because I insisted. After I put a lot of pressure on him, he got to the point where he would make one commit a day, at night, when he was stopping for the day. He would commit to the master branch, because he was confused how to handle different branches. When there was a merge conflict, I would resolve it for him. We worked together for 6 months, and in that time he learned a great deal about a lot of important topics, but he never really learned how to use Git, because it was a low priority, for both him and our CEO.
Git is very powerful? I’m willing to go along with that line of thought so long as we all understand that using a tool that is more powerful than needed can lead to problems.
http://www.smashcompany.com/business/business-productivity-h...
2 replies →
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.
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.
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.
If this is a guide for beginners, there should be (more?) warnings not to do history rewriting operations on commits that have already pushed.
If you read to the bottom:
> Disclaimer: I am not, nor do I even remotely claim to be, an expert at git. This site is not intended to be an exhaustive reference, nor is it a beginner's tutorial. And yes, there are other ways to do these same things with more theoretical purity or whatever, but I've come to these steps through trial and error and lots of swearing and table flipping, and I had this crazy idea to share them with a healthy dose of levity and profanity. Take it or leave it as you will!
From the disclaimer at the bottom:
> This site is not intended to be an exhaustive reference, nor is it a beginner's tutorial.
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.
Why is recovering from an upstream rebase considered more problematic than recovering from merge conflicts?
Who said anything about recovering. First we'll have to determine if upstream is supposed to be used in a rebase workflow or a merge workflow.
Seems they agree:
> This site is not intended to be an exhaustive reference, nor is it a beginner's tutorial.
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.
It happens to everyone :)
I'd like to contribute my list of git booboos: https://github.com/1337/yesterday-i-learned/blob/master/git....
> 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.
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.
> 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?
I think that's exactly what it does; the default is two weeks: https://git-scm.com/docs/git-gc
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.
Is it just me or did http://ohshitgit.com/#accidental-commit-master forget to checkout master before calling reset?
Creating a branch doesn't check it out by default. To do both at once, it's either "checkout -b" or "branch -c", I forget which because it's "b c" in Magit.
Ah, I figured I was missing something.
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?)
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.
Apparently the default behavior is for people who just like to know it's there ;)
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.
Yes, this is another one that confuses developers. When you 'git add' a file, it's added to the staging area as it was at that time. If you make subsequent modifications after you've staged it, those are unstaged changes. And you can diff between them. So despite git add'ing a new file, you still have to 'git add' afterwards if you make changes to it.
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:
"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:
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.
> 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...
1 reply →
For me the big thing was learning to 1/ not work on master unless I’m alone and 2/ commit all my work incrementally
&
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.
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.
A missed opportunity to say gitting instead of getting.
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.
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.)
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.
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/
Maybe it's not worth being in there because of how simple it is, but I guess it would be useful for newcomers:
I think this is bad advice for git newbies two reasons:
1. ‘git add .’ is dangerous and should be avoided IMO, in case you ever have files around that you don’t want to commit. I frequently do. It’s better to ‘git commit -a’, and to just remember to run ‘git status’ frequently and ‘git add’ any new files.
2. ‘git reset —-hard’ is dangerous as well for newbies, since it’s destructive. Better to ‘git revert’ or to ‘git checkout <sha>; git checkout -b <newbranch>’, such that you can always get back to where you were.
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.
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).
git reset --hard for what!? If you are a newcomer making mistakes it is fine for the mistake to be in the commits. Just fix the problem and commit again.
This is a great resource, but I wish the name was different. The oh-shit reference is a bit too much.
Also useful for panicky moments, with handy workflow: http://sethrobertson.github.io/GitFixUm/fixup.html
I visit this page every few weeks. :)
> 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.
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.
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.
In choose your own adventure style: http://sethrobertson.github.io/GitFixUm/fixup.html
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.
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!
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?
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.
Last one in particular: http://ohshitgit.com/#fuck-this-noise
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 :)
Haha. There should be an entry there for 'Oh shit - I just pushed our private keys to the public github repo'.
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.
I use git in this particular way, and if you do anything different you are WRONG AND BAD or you have IMPURE MOTIVES!
Git is easy once you understand it. What are people doing that is so difficult to understand?
Use without understand it
reminds me of https://github.com/blog/2019-how-to-undo-almost-anything-wit...
Pretty basic stuff (and very few of them), I expected more.
Oh shit I give up could instead be `git clean -fdx`
I admit to using this at least once a week.
In short:
| Oh shit, I do before I think
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.
“Oh shit I give up” should perhaps instead be `git clean -fdx`
The very existence of such guides tells us a lot about how easy to use Git is :)
By and large, git is easy to use. Most people will do little beyond committing changes and very occasional branching and merging with the likelihood of not needing any of the tips in the site posted.
For these users, git is perfectly useable and easy to use.
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?
You're comparing git to vim in terms of ease of use...
2 replies →
Well, I think it tells how much time some developers are willing to spend learning the tools they are using.
First of all, using git is not really a choice in many companies (except "choose to use git or choose to find another job"). Because, despite being a terrible tool, "git won". So people like me choose to put the minimum of time in getting familiar with a tool that even some git experts/devs admit is confusing to use (after having used it and being intimately familiar with it for years! or maybe you think they were unwilling to spend enough time learning). More importantly, git (or any DVCS) is NOT work. Lots of technical people seem to have forgotten what purpose versioning control serves (saving your progress as you go) and instead seem to relish in solving git problems that make them feel they're working but add in fact no value whatsoever. That is the core issue. Takes about 10 minutes to get familiar with hg (and then just use a GUI), whereas you have to spend days/weeks reading git docs in order to internalize how it actually works. For what? Just to save some files on a server. I'm sorry, but no.
Truly right
Nothing about detached heads?
You mean, gitting yourself out of bad situations? ( ͡° ͜ʖ ͡°)