Some bad Git situations and how I got myself out of them(ohshitgit.com)
ohshitgit.com
Some bad Git situations and how I got myself out of them
http://ohshitgit.com/
351 comments
Its true -- and actually the well designed gui that accurately depicts the graphical state of your local repository makes it far easier to learn the concepts behind git than does the command line. Distributed vc is conceptually nuanced, but not overly complicated -- the complexity of git really is in the interface wherein you are asked to map command line syntax into abstract operations that manipulate a state that you actually can't easily see from the command line. The value of having a graphical depiction of the state that's changing as you invoke operations should not be underestimated.
http://gitup.co
I love this tool -- it's honestly one of the best graphical tools I've ever used -- rock solid reliable -- intuitive, not leaky in the abstractions it represents -- and not limited to only "simple" operations. And with the graphical reflog history rollback view -- it's always really easy to back up however far you want if you mess up which gives great confidence as you explore the ui's features. Ive taken designers from "never used git" to confidently pushing, pulling, rebasing, and resolving conflicts in less than a day (and most of it after the first 10 minutes without outside help).
http://gitup.co
I love this tool -- it's honestly one of the best graphical tools I've ever used -- rock solid reliable -- intuitive, not leaky in the abstractions it represents -- and not limited to only "simple" operations. And with the graphical reflog history rollback view -- it's always really easy to back up however far you want if you mess up which gives great confidence as you explore the ui's features. Ive taken designers from "never used git" to confidently pushing, pulling, rebasing, and resolving conflicts in less than a day (and most of it after the first 10 minutes without outside help).
Just ran `brew cask install gitup`, cd'd into my repo and ran `gitup`. Took about 60 seconds and so far it's quite impressive.
Clicking on a commit and pressing space brings up a view showing a github-style diff, a list of all changed files, and the complete commit message. Nice.
Thanks for the tip!
Clicking on a commit and pressing space brings up a view showing a github-style diff, a list of all changed files, and the complete commit message. Nice.
Thanks for the tip!
Happy to share!
I had to do a site visit with a customer recently and spent some time pair programming on their codebase -- on a Windows machine and they used an awful git client -- really reminded me how much I appreciate using gitup!
I had to do a site visit with a customer recently and spent some time pair programming on their codebase -- on a Windows machine and they used an awful git client -- really reminded me how much I appreciate using gitup!
Only for iUsers... Really searching for a Linux alternative !
I don't know how it compares to GitUp, but SmartGit works on Linux, Windows, and macOS. I use it on all three platforms and recommend it highly. See my other comment in the subthread for more thoughts about it.
It's not free software though.
True, SmartGit is not open source or free-as-in-speech. It is free-as-in-beer if you use it for open source or noncommercial purposes. I use it for commercial projects and didn't blink at their price - it's paid for itself many times over.
All GUI clients on Linux I tested are plenty of buttons and menus, it makes me cry...
Have you tried GitKraken? https://www.gitkraken.com/
Seems like there's a glut of these apps of late—not that I'm complaining! :-)
Seems like there's a glut of these apps of late—not that I'm complaining! :-)
It's built on electron, though.
Which, as far as I know, works on Linux.
But is not open-source like Linux and Electron are.
Preach! I absolutely love gitup; all of these slice-and-dice operations that are brainteasers in command-line git are just intuitively obvious in gitup. Absolutely one of my favorite pieces of software, ever.
git is basically a brilliant repo model combined with an insane cli. gitup is the brilliant ui that the repo model deserves.
bonus awesome thing about gitup: it monitors the filesystem and updates its state in realtime, so it it's seemless to mix your workflow between cli and gui.
git is basically a brilliant repo model combined with an insane cli. gitup is the brilliant ui that the repo model deserves.
bonus awesome thing about gitup: it monitors the filesystem and updates its state in realtime, so it it's seemless to mix your workflow between cli and gui.
This looks like an awesome way to learn git, and many would probably love to continue with it - but many others too would prefer to move to the CLI.
I used to use a GUI for git, but now I just find them cumbersome; by their nature requiring me to switch window for less.
I used to use a GUI for git, but now I just find them cumbersome; by their nature requiring me to switch window for less.
I actually used to think similarly before I found git up -- although to me
it wasn't about switching window context away from the terminal but rather switching away from the text editor. I imagined that the ideal place for featureful visualization/interaction with the repo would be in the text editor/ide. In reality though -- i really like having the separate window -- it's always there, does one thing and does it well, and it's easy to switch to when I want to take a look at the state of my repo/upstream branches/any dirtiness in my checkout (what exactly have I done recently?). I regularly use three editors when working on different platforms -- Xcode, android studio, atom -- sometimes it's convenient to use in ide repo-driven features (blame, sometimes historical diffs for a single file), however very often I'm actually more interested in quickly seeing diffs for files other than the one(s) I'm currently editing -- so switching to a separate app context that's all about showing repo info tends to be the fastest way to see the relevant info I want side by side without changing away from the editing context I want. More often than not navigating to most relevant diffs within the ide would actually involve more expensive context switching -- for me I'm discovering that it's always somewhat high risk to switch editor contexts -- editing text is just such a powerful interface that it tends to easily lead down rabbit holes that take me further from the most relevant info for my current task context. Once I have the most useful buffers in the right windows, with maybe some reasonable things in the editor navigation stack -- changing the editor views at that point comes with a pretty high risk of straying off task -- or operating for awhile with the non optimal set of editor windows in front of my face -- which at some point I'll realize is dumb/wastes energy and fix -- but energy was already spent in the meanwhile ...
Honestly I'm not aware of any common repo tasks that I could more efficiently complete via the command line vs gitup. There are good keyboard shortcuts for everything in gitup so most everything I do doesn't even involve the mouse.
Also -- I'm the kind of person who's always got a set of terminal windows open and definitely uses them often (almost never use Finder, hate taking my hands off the keyboard to reach for the trackpad). At this point -- I never reach for the git cli over gitup (except when cloning a new repo).
Honestly I'm not aware of any common repo tasks that I could more efficiently complete via the command line vs gitup. There are good keyboard shortcuts for everything in gitup so most everything I do doesn't even involve the mouse.
Also -- I'm the kind of person who's always got a set of terminal windows open and definitely uses them often (almost never use Finder, hate taking my hands off the keyboard to reach for the trackpad). At this point -- I never reach for the git cli over gitup (except when cloning a new repo).
That's interesting. On Linux?
I'm using mac at the moment, and the awful window management (and inability to properly change it - all wm apps just handle resizing and moving within existing spaces and margins) just makes me more motivated to do everything in full-screen tmux, to simulate a decent wm - as long as everything is CLI-based!
(I tried Arch on it for a while, but ended up deciding the firmware difficulties - in particular the battery draining quickly and CPU running hotter - weren't worth it; I traded i3 for full-screened tmux.)
I'm using mac at the moment, and the awful window management (and inability to properly change it - all wm apps just handle resizing and moving within existing spaces and margins) just makes me more motivated to do everything in full-screen tmux, to simulate a decent wm - as long as everything is CLI-based!
(I tried Arch on it for a while, but ended up deciding the firmware difficulties - in particular the battery draining quickly and CPU running hotter - weren't worth it; I traded i3 for full-screened tmux.)
For commands maybe, but nothing beats a graphical history tree. It's hard for a human to imagine a complex branch history without a good visual aid
I agree, and often use a `log --bunch -of --options` alias to view this - but slightly prettier rendering isn't going to make me switch window and back again.
I can't think of a single time I've actually ever cared to look at anything other than a linear history or a single file's blame. I do have a 'hist' alias set up (http://blog.wittchen.biz.pl/basics-of-git/#gist16617665), but it's not something I ever actually use.
Good for you. I'm probably not as smart and more likely to get confused without having the history laid out in the form of a clean, coloured graph. At any rate, it allows me to free whatever brain power I have for other purposes
I had a look at the tool, watched the screencast and was impressed. Then I saw, at the very bottom that this is for Macs. The disappointment...
I have to disagree, I've seen people paint themselves into really hard to get out of corners by using GUI tools and not understanding the underlying tool. git GUIs are leaky abstractions that sometimes even change the meaning of core git concepts. I always recommend people start by using git at the command line until the have a solid understanding of how the tool works before switching to a GUI.
Yes. I teach git professionally and when I do, my approach is to stick to describing the nuts and bolts. Once people use it from the command line and get things done, they (usually) understand what's going on pretty well but are annoyed by the nitty gritties of the command line. Then they're ready to move on to a tool of their choice but can always map the actions there back to the data structures inside git so they've never lost. Also, they can always drop back down to the command line for any low level surgery that the client doesn't provide.
I use magit myself for most things.
I use magit myself for most things.
I completely agree with this one. I encourage our developers to always use the cli, even if they are not familiar with the core concepts of git. I see myself as a mediocre git user, but there are some situations, however, where I prefer to use a GUI for more complex operations, like staging/un-staging specific lines or create/apply patches.
I'm with you. I've been using SmartGit for years and would never go back to the weak sauce of the command line, except for a few odd things that SmartGit doesn't cover (like bisect).
Every one of the tasks in the article is a simple, straightforward operation in SmartGit. Take "I accidentally committed something to master that should have been on a brand new branch!" or "I accidentally committed to the wrong branch!" for example.
Instead of an obscure series of four to six commands, you simply go to SmartGit's log view and drag the branch markers to where you want them. Easy and intuitive.
I know GUI tools are a hard sell for a lot of programmers. I honestly don't understand why. I think it may be the fear that you'd be giving up power, but SmartGit isn't a dumbed-down GUI. It gives you a more powerful set of tools, and much more visibility into the state of your repo.
You're not even giving anything up. You can still use the command line whenever you want, and SmartGit shows you the commands it used to accomplish each task.
Of course you still need to understand the underlying Git concepts to use any GUI effectively, but a tool like SmartGit lets you see those concepts.
Every one of the tasks in the article is a simple, straightforward operation in SmartGit. Take "I accidentally committed something to master that should have been on a brand new branch!" or "I accidentally committed to the wrong branch!" for example.
Instead of an obscure series of four to six commands, you simply go to SmartGit's log view and drag the branch markers to where you want them. Easy and intuitive.
I know GUI tools are a hard sell for a lot of programmers. I honestly don't understand why. I think it may be the fear that you'd be giving up power, but SmartGit isn't a dumbed-down GUI. It gives you a more powerful set of tools, and much more visibility into the state of your repo.
You're not even giving anything up. You can still use the command line whenever you want, and SmartGit shows you the commands it used to accomplish each task.
Of course you still need to understand the underlying Git concepts to use any GUI effectively, but a tool like SmartGit lets you see those concepts.
I've worked with a guy who only uses GUI tools for Git and he's supposed to be a senior dev and doesn't know how to resolve a simple merge conflict and regularly wipes out other peoples' work with whatever he's doing with the tool.
No thanks.
No thanks.
I agree. If you use something like SourceTree, you can also see the git command, in case you end up needing to know what it is. Best of both worlds.
I mainly use the GUI for day-to-day stuff. Only in rare cases will I need to mess with the command line.
I mainly use the GUI for day-to-day stuff. Only in rare cases will I need to mess with the command line.
I like to use a GUI for things like viewing staged/unstaged files, their riffs, and picking which files to stage for a commit, but for every other situation, the command line is just so much faster and easier to understand what's actually happening.
I stopped using a GUI (SmartGit) when I encountered an error which was talking about stashes and something like {0}. I had no idea what the error was. Now I know how these tools work but I think that you can only use them effectively if you learn how they work and how the underlying system works. If you fail to do so you end up with a leaky abstraction which will at some point (and believe me it will) present you with an error message you don't understand and you end up with a problem you can't recover (yet). GUIs are fine but only if you know the ins and outs of the underlying system.
Agreed, a GUI have most of the functionality and a clear visual representation of the state of your repo.
When it's not enough the terminal is once click away
Interesting. I've always been too scared of git GUIs to seriously try them out. The fear being I will somehow mess up the repo by using the GUI wrong.
I am surprised that somebody claim that has messed up a git repo. Since I started using git, I haven't ever messed up with my code.
I always use git on the command line. Regarding GUI tools I like to avoid them, for me is too much noise. People get lost most of the time because they don't know what the tool is doing. After all is just one more layer on top of git core tool per se (aka, what you have in command line).
I always use git on the command line. Regarding GUI tools I like to avoid them, for me is too much noise. People get lost most of the time because they don't know what the tool is doing. After all is just one more layer on top of git core tool per se (aka, what you have in command line).
I've never really screwed it up that badly using the command line either. I don't know what these people are trying to do that they constantly mess up their repository so bad they can't fix it. Perhaps being too obsessed with having a perfect commit history.
I'm curious: What are the best free GUI for Git?
I'm surprised nobody mentioned Git Extensions yet. My absolute favorite Git UI, better than my previously favorite git-cola.
https://gitextensions.github.io/
https://gitextensions.github.io/
I'm a big fan of GitLab. Clean design, intuitive interface, many features.
Disclaimer: I'm now a GitLab authorized training partner and reseller. The community edition is free. :)
Disclaimer: I'm now a GitLab authorized training partner and reseller. The community edition is free. :)
I'm a fan of tig on the command line and Gitbox (Mac GUI).
gitk - it's built into git, and supplements (not replaces) the command line. It does tree visualization and diffs between commits.
Magit
Sourcetree, if you are not on Linux like me :(
I've seen repos completely borked because the gui kept a merging and pushing in the background. This was after spending a lot of time removing binaries from a repo and not being able to figure out how the same binaries kept ending up back on origin.
Sure, it's harder to screw up. But, dang it's just so remarkably slow.
If you're used to the commands from the keyboard, where you're likely already typing from your editor...can't imagine going back to the GUI.
If you're used to the commands from the keyboard, where you're likely already typing from your editor...can't imagine going back to the GUI.
I agree, and while I have not tried the other apps mentioned here, I do rely extensively on Atlassian SourceTree client for Mac and find it very useful.
I feel more comfortable and faster using git commands that a GUI.
One of the nice workflows that's already built in to the git command line tools is this one. When you're working on a branch and realise that a commit you made a few commits back has a mistake in it:
Handy enough that I set rebase.autoSquash to true in my ~/.gitconfig so 'git rebase -i' always works like this.
# Make correcting change
git commit --all --fixup=<ref of commit with mistake>
# Continue working on branch, then at some point
git rebase --interactive --autosquash
The --fixup option creates commits with subjects formatted like 'fixup! previous commit subject'. --autosquash uses these subjects when building the interactive rebase list.Handy enough that I set rebase.autoSquash to true in my ~/.gitconfig so 'git rebase -i' always works like this.
Yeah, super useful, I can second setting auto squash in the config. I was almost thinking of saying the same thing, but I realized this post is probably deliberately avoiding rebase. This workflow is advanced relative to the problems described, and you'd agree those command lines are going to look pretty intimidating to a novice, right? They were to me the first time, there's a lot to understand before they're comfortable.
> This workflow is advanced relative to the problems described
Yeah, true. I posted it mostly because one of the bigger threads of comments was advocating using a GUI instead of the CLI. I'm not going to argue that the git CLI is simple, but it does have some nice features to support specific common workflows.
Yeah, true. I posted it mostly because one of the bigger threads of comments was advocating using a GUI instead of the CLI. I'm not going to argue that the git CLI is simple, but it does have some nice features to support specific common workflows.
Yep. I find that most of the time, the commit I want to fixup is my last one, so I don't even need the interaction. I use this script almost every day:
last_commit=$(git log --oneline | head -1 | cut -d' ' -f1)
git commit -a --fixup ${last_commit}
GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash ${last_commit}~1Somebody proposed to use a GUI. That doesn't solve the usability issues of Git. There's this triangle of what the user tries to do, what the commands and options are called and what they actually do. None of them really align, though with some careful use you can actually make Git do what you want - eventually.
I would like to understand what's the yearly damage of such an important tool being so difficult to use. People committing the wrong stuff, unmergeable messes, people not being able to correct their mistakes, there must be thousands of Git rookies fucking up their Git repo or throwing away their work just as I am writing this.
What would be the cost? Millions of Dollars? Perhaps even billions?
It's about as bad as 0 being a legit value for a regular pointer.
I would like to understand what's the yearly damage of such an important tool being so difficult to use. People committing the wrong stuff, unmergeable messes, people not being able to correct their mistakes, there must be thousands of Git rookies fucking up their Git repo or throwing away their work just as I am writing this.
What would be the cost? Millions of Dollars? Perhaps even billions?
It's about as bad as 0 being a legit value for a regular pointer.
God, it's probably billions. I love git but its user interface is borderline criminal. The sad thing is mercurial has like 95% of git's power and is waaay easier to understand, but it never took off in a big way.
> The sad thing is mercurial has like 95% of git's power and is waaay easier to understand
Mercurial has a clean and simple UI, especially if you come from a SVN background.
But Git's internals are simpler and the concept is much easier to understand, especially if you start looking at a handful of the most popular Mercurial extensions, some of which will be "must have" sooner or later.
This is no excuse for an inconsistent UI in Git, but the damage is already done. There's no point in making major changes now (some renaming for consistency might be alright, though), it would be breaking existing workflows and scripts.
I find the best explanation of how Git works is... the first commit of Git[0] itself.
[0] https://github.com/git/git/commit/e83c5163316f89bfbde7d9ab23...
Mercurial has a clean and simple UI, especially if you come from a SVN background.
But Git's internals are simpler and the concept is much easier to understand, especially if you start looking at a handful of the most popular Mercurial extensions, some of which will be "must have" sooner or later.
This is no excuse for an inconsistent UI in Git, but the damage is already done. There's no point in making major changes now (some renaming for consistency might be alright, though), it would be breaking existing workflows and scripts.
I find the best explanation of how Git works is... the first commit of Git[0] itself.
[0] https://github.com/git/git/commit/e83c5163316f89bfbde7d9ab23...
>But Git's internals are simpler and the concept is much easier to understand,
I'm only an occasional Git user, but am a heavy Mercurial user.
I have never needed to understand Mercurial's internals.
Are you suggesting a Git user will eventually need to understand it? That's a strike against Git already.
From my observation over the years, people who use Git get "stuck" more often, because they are trying to leverage the extra power Git seems to provide. With Mercurial, you often can do similar powerful stuff, but they make sure you have to go through hoops to do it. As such, unsuspecting non-power users do not shoot themselves in the foot.
I'm only an occasional Git user, but am a heavy Mercurial user.
I have never needed to understand Mercurial's internals.
Are you suggesting a Git user will eventually need to understand it? That's a strike against Git already.
From my observation over the years, people who use Git get "stuck" more often, because they are trying to leverage the extra power Git seems to provide. With Mercurial, you often can do similar powerful stuff, but they make sure you have to go through hoops to do it. As such, unsuspecting non-power users do not shoot themselves in the foot.
Are you suggesting a Git user will eventually need to understand it? That's a strike against Git already.
The typical advice -- which you'll see in this thread and elsewhere -- is that anyone who uses git should learn git's internals, and preferably up-front, since apparently that will magically cause git to make sense.
I'm a bit put off by the idea, myself.
The typical advice -- which you'll see in this thread and elsewhere -- is that anyone who uses git should learn git's internals, and preferably up-front, since apparently that will magically cause git to make sense.
I'm a bit put off by the idea, myself.
Exactly.
It's also worth looking at git internals because it's very elegant, clean and simple. In my opinion, one of the best designed software systems I've come across.
I encourage you to look at the README in the first git commit, it's very enlightening.
It's also worth looking at git internals because it's very elegant, clean and simple. In my opinion, one of the best designed software systems I've come across.
I encourage you to look at the README in the first git commit, it's very enlightening.
>Are you suggesting a Git user will eventually need to understand it? That's a strike against Git already.
I think as engineers we should understand how our tools work.
I think as engineers we should understand how our tools work.
> Are you suggesting a Git user will eventually need to understand it? That's a strike against Git already.
I try to learn about git internals just for the pleasure of it.
I try to learn about git internals just for the pleasure of it.
I think Mercurial is also great, and we also can provide some feedback as the platform that supports Mercurial as Source Code Management (RhodeCode).
There are A LOT of mercurial users which are big companies, they just aren't so vocal on the internal like people using GIT. Mercurial has an established community, great plugability system, an awesome feature like phases.
We see more and more people adopting Mercurial together with our product.
I wish to see more advocates of Mercurial, it's a shame it doesn't get more public attention nowadays.
There are A LOT of mercurial users which are big companies, they just aren't so vocal on the internal like people using GIT. Mercurial has an established community, great plugability system, an awesome feature like phases.
We see more and more people adopting Mercurial together with our product.
I wish to see more advocates of Mercurial, it's a shame it doesn't get more public attention nowadays.
$ hg clone https://bitbucket.org/eigen/eigen/
$ cd eigen
$ time hg grep CUDA > /dev/null
real 0m16.661s
user 0m16.097s
sys 0m0.531s
$ git clone https://github.com/RLovelett/eigen.git
$ cd eigen
$ time git grep CUDA > /dev/null
real 0m0.019s
user 0m0.035s
sys 0m0.057s
Never looked back.Well, you can just use the silver searcher with both. This is not a great argument for a better DVCS.
As Jtsummers pointed out downthread, hg grep searches all revisions by default. No wonder it's so slow.
$ time hg grep --rev tip CUDA > /dev/null
real 0m0.075s
user 0m0.055s
sys 0m0.020s
Much better. Still much slower than git, which doesn't matter for this small repo but would definitely matter on a larger repo. But better. And hg lets you define aliases, so you don't have to remember to type "--rev tip".The biggest differences for me are:
* Network effect. Almost any dev can use git, so it's our "common language". * Staging area. Mercurial doesn't have one, which I find is enough to make me never look back.
* Network effect. Almost any dev can use git, so it's our "common language". * Staging area. Mercurial doesn't have one, which I find is enough to make me never look back.
this is a highly misleading comparison. something slightly more accurate (although this time somewhat more hg-biased):
$ time taskset -c 2 hg grep CUDA >/dev/null
taskset -c 2 hg grep CUDA > /dev/null 25.04s user 0.46s system 99% cpu 25.514 total
$ time taskset -c 2 sh -c 'git grep --cached -l CUDA | xargs -n 1 git blame >/dev/null'
taskset -c 2 sh -c 4.85s user 0.13s system 97% cpu 5.097 total> this is a highly misleading comparison.
Why? When I do hg grep, it doesn't show me blame or anything; the output looks almost identical to the output of git grep. If it's doing work and then throwing it away, why is it fair to force git to do the same work and then also throw it away?
(I'll also point out that git is still 5x faster in this comparison. :)
Why? When I do hg grep, it doesn't show me blame or anything; the output looks almost identical to the output of git grep. If it's doing work and then throwing it away, why is it fair to force git to do the same work and then also throw it away?
(I'll also point out that git is still 5x faster in this comparison. :)
Did you run hg grep once before to keep it in the disk cache?
It seems I cannot post a performance comparison without people asking about disk caches. :)
First of all, if I just cloned the repos, they should be in disk cache. My machine has 64GB of RAM.
Second of all, if they're not in disk cache, what on earth is hg doing that it takes 16 seconds to read them all in? Eigen is not that big, and I have a fast SSD.
Third of all, you can run the tests yourself -- I gave you the exact commands to try. "I tried it and my results are X" is a much better contribution to the discussion.
Fourth of all, yes, I ran the benchmarks multiple times in a row to check whether disk cache was at play. It was not. :)
First of all, if I just cloned the repos, they should be in disk cache. My machine has 64GB of RAM.
Second of all, if they're not in disk cache, what on earth is hg doing that it takes 16 seconds to read them all in? Eigen is not that big, and I have a fast SSD.
Third of all, you can run the tests yourself -- I gave you the exact commands to try. "I tried it and my results are X" is a much better contribution to the discussion.
Fourth of all, yes, I ran the benchmarks multiple times in a row to check whether disk cache was at play. It was not. :)
> It seems I cannot post a performance comparison without people asking about disk caches. :)
Sorry, the speedup was very great so it almost seemed like something else was causing it. Thanks for the benchmarks.
> Third of all, you can run the tests yourself -- I gave you the exact commands to try. "I tried it and my results are X" is a much better contribution to the discussion.
That's true; I'm lazy.
Actually, I was thinking more of the disk cache of loading hg, not the repo (Python programs tend to have a great speedup through the disk cache).
Sorry, the speedup was very great so it almost seemed like something else was causing it. Thanks for the benchmarks.
> Third of all, you can run the tests yourself -- I gave you the exact commands to try. "I tried it and my results are X" is a much better contribution to the discussion.
That's true; I'm lazy.
Actually, I was thinking more of the disk cache of loading hg, not the repo (Python programs tend to have a great speedup through the disk cache).
I think the implication is that the freshly checked out state of the files was used.
I do agree that reproducible differences in performance should be measured, not single tests.
I do agree that reproducible differences in performance should be measured, not single tests.
This is also why I prefer using C over Python.
(End Sarcasm).
Seriously? You're so productive that the cost of cloning a repository is a major impediment?
The benefits of a cleaner interface mostly trump the benefits of speed.
(End Sarcasm).
Seriously? You're so productive that the cost of cloning a repository is a major impediment?
The benefits of a cleaner interface mostly trump the benefits of speed.
> Seriously? You're so productive that the cost of cloning a repository is a major impediment?
Read the commands more carefully. It is not the cost of cloning the repository, but rather the cost of searching it.
Read the commands more carefully. It is not the cost of cloning the repository, but rather the cost of searching it.
Ah. My mistake.
16s is not a big deal, but I'm assuming it would get much worse for larger repositories.
Personally, my searches are either:
1. Restricted to all files that end in cpp, h, py, pl, etc.
2. Explicitly exclude .hg directories.
I'll confess: I use a nice tool to do my searches than typing it out in grep. Much handier. And it remembers previously used filters (.cpp,.h) and is usually the first item in the drop down box. Much quicker than typing out a grep command.
Still, I feel if our team used git instead of hg, we'd lose a lot more time due to people not grokking git and making mistakes than the time lost in longer searches.
My point still stands: Things like search time are not a productivity bottleneck. If all our searches were 100x faster, there would be no difference in our output.
16s is not a big deal, but I'm assuming it would get much worse for larger repositories.
Personally, my searches are either:
1. Restricted to all files that end in cpp, h, py, pl, etc.
2. Explicitly exclude .hg directories.
I'll confess: I use a nice tool to do my searches than typing it out in grep. Much handier. And it remembers previously used filters (.cpp,.h) and is usually the first item in the drop down box. Much quicker than typing out a grep command.
Still, I feel if our team used git instead of hg, we'd lose a lot more time due to people not grokking git and making mistakes than the time lost in longer searches.
My point still stands: Things like search time are not a productivity bottleneck. If all our searches were 100x faster, there would be no difference in our output.
16 seconds versus a fraction of a second. There's a big difference, somewhere, in what these two systems are doing to accomplish (ostensibly) the same task. And if it's not accomplishing the same task, they shouldn't be using the same verb (grep) for it.
And I disagree with this point:
Not having looked at the internals of either, I wonder if this is related to other performance differences in grep implementations across *nix systems.
EDIT: Exploring this, it seems they don't do the same thing? `git grep` searches, by default, only the most recent working tree or revision. It doesn't search every revision unless you tell it to. `hg grep` (don't have it installed) seems to search every revision by default, so restricting it to the current revision requires an explicit command line option specifying the revision range to search.
And I disagree with this point:
Things like search time are *not* a productivity bottleneck.
I maintain old codebases. I don't know them by heart, I didn't write them and the documentation is often poor (for the codebase, the specs are usually decent, but that's the system spec, not the code spec). Search is critical for me to get around these things. A 16s search would be incredibly annoying and bottlenecking compared to one that's nearly instant.Not having looked at the internals of either, I wonder if this is related to other performance differences in grep implementations across *nix systems.
EDIT: Exploring this, it seems they don't do the same thing? `git grep` searches, by default, only the most recent working tree or revision. It doesn't search every revision unless you tell it to. `hg grep` (don't have it installed) seems to search every revision by default, so restricting it to the current revision requires an explicit command line option specifying the revision range to search.
Things like search time are *not* a productivity bottleneck.
I would recommend, as a general rule, not generalizing from your development experience to everyone's development experiences.I happen to know that git grep is very carefully optimized. Someone cared a lot about making it run fast. Seems like a good guess that they did so because it was important to them or someone else, not just for funzies.
$ grep '^git grep' ~/.bash_history | wc -l
407
$ grep -w '^ls' ~/.bash_history | wc -l
37
$ wc -l ~/.bash_history
19421
"git grep" is 2% of all the commands I type. I type it 10x as often as "ls". So, yeah, its speed matters to me. :)>"git grep" is 2% of all the commands I type. I type it 10x as often as "ls". So, yeah, its speed matters to me. :)
I appreciate that - I know the frustration of tools being a bit laggy.
However, I think you are falling for the [Endowment Effect](https://en.wikipedia.org/wiki/Endowment_effect). You are accustomed to it, so the alternative seems horrible without you really thinking it through. If you were not already using grep, the search issue would not be a big deal.
I already pointed out how merely excluding ".hg" from your search will save all the time, and this benefit you speak of disappears (please correct me if I'm wrong).
On my shell, that's as simple as creating an alias for grep to always exclude ".hg".
Yes, I'll grant that searching Mercurial repositories is a lot slower. But you need to understand that the obvious solution is not "Switch to git". There are simpler solutions.
In that sense, this seems to be a very insignificant benefit of git, even for people like you who need to search often.
To beat a dead horse, if you had two developers: One using git and the other using mercurial, and both need to search heavily, the mercurial person will likely have already solved the problem in one way or another. It'd be a bit silly for an observer to look at them and say "Ah, Git is so much better because it did not require a shell alias for faster searches!"
I appreciate that - I know the frustration of tools being a bit laggy.
However, I think you are falling for the [Endowment Effect](https://en.wikipedia.org/wiki/Endowment_effect). You are accustomed to it, so the alternative seems horrible without you really thinking it through. If you were not already using grep, the search issue would not be a big deal.
I already pointed out how merely excluding ".hg" from your search will save all the time, and this benefit you speak of disappears (please correct me if I'm wrong).
On my shell, that's as simple as creating an alias for grep to always exclude ".hg".
Yes, I'll grant that searching Mercurial repositories is a lot slower. But you need to understand that the obvious solution is not "Switch to git". There are simpler solutions.
In that sense, this seems to be a very insignificant benefit of git, even for people like you who need to search often.
To beat a dead horse, if you had two developers: One using git and the other using mercurial, and both need to search heavily, the mercurial person will likely have already solved the problem in one way or another. It'd be a bit silly for an observer to look at them and say "Ah, Git is so much better because it did not require a shell alias for faster searches!"
I would recommend, as a general rule, not generalizing from your development experience to everyone's development experiences.
What's interesting here is that it's the exact thing happening. Someone asked about how much hidden cost there is from the time people waste fighting to make git do what they need it to do, and it got derailed with a discussion of how `git grep` is faster than `hg` grep`.
I'm sure it's great for you that git's grep is fast. But the time you gain from how much faster it is than hg probably is strongly outweighed by the time other people lose to struggling with git's interface. Unfortunately there's no easy way to benchmark that.
What's interesting here is that it's the exact thing happening. Someone asked about how much hidden cost there is from the time people waste fighting to make git do what they need it to do, and it got derailed with a discussion of how `git grep` is faster than `hg` grep`.
I'm sure it's great for you that git's grep is fast. But the time you gain from how much faster it is than hg probably is strongly outweighed by the time other people lose to struggling with git's interface. Unfortunately there's no easy way to benchmark that.
Yes, it does 95% of what git does, and very well.
The problem, that I don't think anybody even expected, is that there are strong network effects on the selection of your CVS. That gives the tool that can handle more use cases a big advantage, and bigger still if those features are needed on the projects with more developers.
The problem, that I don't think anybody even expected, is that there are strong network effects on the selection of your CVS. That gives the tool that can handle more use cases a big advantage, and bigger still if those features are needed on the projects with more developers.
Mercurial was a lot harder to understand for me, and had no staging index -- stuff is committed directly. I found that this made it incredibly hard to use, especially coming from git.
I feel like people's opinion of git's usability is lower than what it actually is.
Certainly, it's got a lot of different switches and stuff, but since its data model is so simple, you can always understand what it's doing to your data. So you can read a description of what a switch does, and then understand exactly what will happen when you use it.
(The exception to this is automatic merge conflict resolution with rerere, which is just magic to me. But it's a bonus feature anyway)
For me, as a long time git user, git's UI and UX is approximately a bajillion times better than something like SVN, which can barely even do half the things that I use every day in git.
Maybe I haven't just dug deep enough into Subversion's manual, but can you tell me how to do the equivalent of "git log -p"? Last time I checked (SVN 1.8) that's not very trivial. Or how to revert a commit? IIRC that requires a merge.
So at least compared to subversion, git enables a workflow that was previously too much work, and gives me a better tool for working with version-controlled text data.
Mercurial is another thing I find puzzling, and I'm honestly interested why it is that people find it so much easier to use than git. I'm so used to working with throw-away branches that hg's default branching model just feels needlessly difficult to me, and good support for managing branches is the most important feature of a VCS, since any change you ever make is automatically a branch from the base. In git, this feels natural, since branches are a feature of the underlying data model, not something treated specially.
Certainly, it's got a lot of different switches and stuff, but since its data model is so simple, you can always understand what it's doing to your data. So you can read a description of what a switch does, and then understand exactly what will happen when you use it.
(The exception to this is automatic merge conflict resolution with rerere, which is just magic to me. But it's a bonus feature anyway)
For me, as a long time git user, git's UI and UX is approximately a bajillion times better than something like SVN, which can barely even do half the things that I use every day in git.
Maybe I haven't just dug deep enough into Subversion's manual, but can you tell me how to do the equivalent of "git log -p"? Last time I checked (SVN 1.8) that's not very trivial. Or how to revert a commit? IIRC that requires a merge.
So at least compared to subversion, git enables a workflow that was previously too much work, and gives me a better tool for working with version-controlled text data.
Mercurial is another thing I find puzzling, and I'm honestly interested why it is that people find it so much easier to use than git. I'm so used to working with throw-away branches that hg's default branching model just feels needlessly difficult to me, and good support for managing branches is the most important feature of a VCS, since any change you ever make is automatically a branch from the base. In git, this feels natural, since branches are a feature of the underlying data model, not something treated specially.
> [C]an you tell me how to do the equivalent of "git log -p"? Last time I checked (SVN 1.8) that's not very trivial.
svn log --diff, added in 1.9. Also doable with a little (est. < 10 lines) of shell scripting.
> Or how to revert a commit? IIRC that requires a merge.
git and svn disagree on whether history should be permanent or not.
svn log --diff, added in 1.9. Also doable with a little (est. < 10 lines) of shell scripting.
> Or how to revert a commit? IIRC that requires a merge.
git and svn disagree on whether history should be permanent or not.
Except very few actually take the time to understand the data model..
People complain, but what's the alternative?
Non-distributed VCS clearly don't cut it for many use cases, and of the other DVCS I've tried, none were really better than Git in my opinion.
Sure, it depends on your workflow. But if part of your workflow is authoring sequences of commits that make sense in hindsight, then I honestly haven't seen an alternative.
The point of Git is that it gets the underlying data model right, and just exposes that. Once you grok that, it is superior to everything else.
If you don't grok it, you have a problem. For this reason, I think GUIs are actually somewhat detrimental for Git use. git gui and gitk serve a purpose, and they could definitely need some polish, but my other explorations into Git GUIs have basically turned out to be badly done and leaky abstractions which hurt more than they help.
Non-distributed VCS clearly don't cut it for many use cases, and of the other DVCS I've tried, none were really better than Git in my opinion.
Sure, it depends on your workflow. But if part of your workflow is authoring sequences of commits that make sense in hindsight, then I honestly haven't seen an alternative.
The point of Git is that it gets the underlying data model right, and just exposes that. Once you grok that, it is superior to everything else.
If you don't grok it, you have a problem. For this reason, I think GUIs are actually somewhat detrimental for Git use. git gui and gitk serve a purpose, and they could definitely need some polish, but my other explorations into Git GUIs have basically turned out to be badly done and leaky abstractions which hurt more than they help.
I like Git generally, and my feelings on GUIs for it are kinda mixed. I like GUIs for visualizing the log with all branches, and they make it easier to selectively commit some of your changes, especially partial files. I haven't seen any that are much help over the command line for managing branching and merging, though. I like GitX for OS X because it does the things that I think GUIs are good at, and doesn't try to do much else.
Many large companies use Perforce. Its UI is great. It's very easy to learn, so the cost of teaching new employees is low. It's hard to screw up, and when you do screw up, it doesn't require an expert to come in and fix things with obscure commands.
I'm genuinely curious if this isn't an effect of biased in favour of what you know (on both sides, possibly). I found Perforce to be terribly opaque. Perhaps this is because the good stuff is buried amidst enterprise nonsense, but compare the experience of going to git-scm.com versus perforce.com if your goal is to learn.
(Not to mention the fact that Perforce as I know it simply doesn't cover the distributed use cases that Git does. Obviously adding distributed features makes any VCS more complex, but that is the inherent complexity of the problem space as opposed to artificial complexity. If your problem is conceptually easier, you can make the solution appear easier.)
(Not to mention the fact that Perforce as I know it simply doesn't cover the distributed use cases that Git does. Obviously adding distributed features makes any VCS more complex, but that is the inherent complexity of the problem space as opposed to artificial complexity. If your problem is conceptually easier, you can make the solution appear easier.)
I absolutely love git now.
I'm still at uni (at a highly ranked but actually crap university where we don't learn git properly) and this year was my 'year in industry' as we call it in the UK, and my first proper experience with git, aside from `git init` at the end of my project and pushing it to a repo.
I've become so much more confident with git. Seriously, with one caveat (i.e., you haven't pushed your changes to a branch which other developers are working on), it is almost impossible to break irrevocably. Even if you do accidentally break master/develop/whatever, it only causes a bit of hassle and grumbling.
Highly recommend that everyone take a bit of time to learn about "undoing" git commands, whether that's through soft resets, hard resets to origin, or the reflog.
Reflog is also useful for figuring out how someone else broke something and explaining what they did wrong, since you can see what branch they were on at what commit and what commands they ran.
I think git's main problem is the somewhat arcane language it uses, and lack of understanding of what's actually happening behind those words like "rebase", "commit", "patch", "reset" etc.
I'm still at uni (at a highly ranked but actually crap university where we don't learn git properly) and this year was my 'year in industry' as we call it in the UK, and my first proper experience with git, aside from `git init` at the end of my project and pushing it to a repo.
I've become so much more confident with git. Seriously, with one caveat (i.e., you haven't pushed your changes to a branch which other developers are working on), it is almost impossible to break irrevocably. Even if you do accidentally break master/develop/whatever, it only causes a bit of hassle and grumbling.
Highly recommend that everyone take a bit of time to learn about "undoing" git commands, whether that's through soft resets, hard resets to origin, or the reflog.
Reflog is also useful for figuring out how someone else broke something and explaining what they did wrong, since you can see what branch they were on at what commit and what commands they ran.
I think git's main problem is the somewhat arcane language it uses, and lack of understanding of what's actually happening behind those words like "rebase", "commit", "patch", "reset" etc.
I would not expect a university to teach git. Maybe the theory of version control systems, their history, or a comparison of different version control systems.
But not how to use the tool.
But not how to use the tool.
I agree. Class time is much too valuable to be lost on such minutiae. However, I'd expect a good university to:
a) Explain the value of version control and actively promote its usage
b) Drop some hints on which good version control systems are out there, one of which is git, then let students pick, learn and run with their own choice
It'd take all of half an hour, with great benefits for students.
a) Explain the value of version control and actively promote its usage
b) Drop some hints on which good version control systems are out there, one of which is git, then let students pick, learn and run with their own choice
It'd take all of half an hour, with great benefits for students.
I agree because of the large variety of version control tools. Git is great IMHO, but not every company uses it or can easily switch to it. Teach some theory or the basics of a few different systems and their pros and cons, but I don't think diving too deeply into only one is a good idea in a university environment.
Perhaps not specifically git, but ANY version control would have been good.
We were told to version control a group project, but all we were given was an SVN repo and told "if anything goes wrong, email this address".
Personally I would expect tuition through the use of a tool, that tool doesn't have to be git, it just so happens to be the tool I've had the most exposure to.
We were told to version control a group project, but all we were given was an SVN repo and told "if anything goes wrong, email this address".
Personally I would expect tuition through the use of a tool, that tool doesn't have to be git, it just so happens to be the tool I've had the most exposure to.
I had to take a class, Principles of Software Engineering, that was a sort of hands-on class. We went over different methodoligies like waterfall vs agile, scrum, the use of kanban boards, design documents, and the use of version control. The version control lession was basically an assignment saying "do the Udacity git course". Alongside this, we had a group project where we had to, well, develop something.
I agree that the syntax is nonintuitive.
it is almost impossible to break irrevocably.
This tells me you still don't get the point about using a revision control system: the whole point is NOT that you can hack the revision control system's database every which way, but that you can never, as in ever, break something in a repository, because you can always revert the previous commit and do a new commit of that revert. Keeping it simple since January 1st, 1970.
It's called the "unceremonious revert", popularized by Jeff Bonwick, the father of ZFS and former Solaris gatekeeper, in the "Quality death spiral":
Bonwick was granted authority to "rip it out if itʼs broken" — an early BDFL model, and a template for later generations of engineering leadership.
https://web.archive.org/web/20091028095830/http://hub.openso...
https://wiki.smartos.org/display/DOC/Community+History
SEE ALSO
http://dtrace.org/blogs/bmc/2015/09/03/software-immaculate-f...
...and do youserlf a favor, try out Bitkeeper (it's open source!) before you get completely absorbed into git. You might never be able to get out of that tar pit afterwards, or it might be decades before you realize it. Who will compensate you for all that lost time, and how would you be compensated?
This tells me you still don't get the point about using a revision control system: the whole point is NOT that you can hack the revision control system's database every which way, but that you can never, as in ever, break something in a repository, because you can always revert the previous commit and do a new commit of that revert. Keeping it simple since January 1st, 1970.
It's called the "unceremonious revert", popularized by Jeff Bonwick, the father of ZFS and former Solaris gatekeeper, in the "Quality death spiral":
Bonwick was granted authority to "rip it out if itʼs broken" — an early BDFL model, and a template for later generations of engineering leadership.
https://web.archive.org/web/20091028095830/http://hub.openso...
https://wiki.smartos.org/display/DOC/Community+History
SEE ALSO
http://dtrace.org/blogs/bmc/2015/09/03/software-immaculate-f...
...and do youserlf a favor, try out Bitkeeper (it's open source!) before you get completely absorbed into git. You might never be able to get out of that tar pit afterwards, or it might be decades before you realize it. Who will compensate you for all that lost time, and how would you be compensated?
I think you misunderstood @mathieuh's statement, which is why you are being downvoted.
@mathieuh was only referring to not being able to break the something in the repo, He didn't mention hacking the git or the git data structure.
Also, @mathieuh is a uni student, so comments like
> This tells me you still don't get the point about using a revision control system
Can come across a little unnice.
@mathieuh was only referring to not being able to break the something in the repo, He didn't mention hacking the git or the git data structure.
Also, @mathieuh is a uni student, so comments like
> This tells me you still don't get the point about using a revision control system
Can come across a little unnice.
And? You will have some kind of 'blessed' repo anyway. In git you disable non-fast-forward pushes there (aka prevent commits from ever being removed) there, and implemented your 'point'.
See also 'svn obliterate'.
See also 'svn obliterate'.
A somewhat lesser known git trick that's pretty much a strict improvement - use `--force-with-lease` for force pushing instead of `--force`.
What this does is check what's on the remote branch and compare it with what you think is on the remote branch, and only do the force if they're the same thing. So if someone pushes a commit, the force push errors out instead of silently overwriting it.
Basically every single time you want to force push, you probably should be doing a `--force-with-lease` instead. I can't think of a situation where you'd want to silently lose commits you don't know about rather than get an error.
What this does is check what's on the remote branch and compare it with what you think is on the remote branch, and only do the force if they're the same thing. So if someone pushes a commit, the force push errors out instead of silently overwriting it.
Basically every single time you want to force push, you probably should be doing a `--force-with-lease` instead. I can't think of a situation where you'd want to silently lose commits you don't know about rather than get an error.
I also can't think of a situation where you'd want to force push to a branch that others might be committing to.
If they're not committing to it, --force-with-lease is the same thing as --force, so it doesn't cost you anything.
Costs ten keystrokes by my count. But it's not the keystrokes that trouble me, it's the idea that one of my co-collaborators might use this feature to "safely" rewrite history in a branch I'm also using. "Safely" being relative, since the rest of the collaborators will have to force pull that branch later, and rebase their pending changes.
By my reckoning, rewriting history just isn't a reasonable decision in shared branches.
By my reckoning, rewriting history just isn't a reasonable decision in shared branches.
One thing not covered very well was what to do if you push to origin. My favourite way to fix this: use git revert to create an exact opposite commit to your bad commit.
git revert <bad commit>
git push
It leaves a history of the mistake, for better or worse, but it does undo the mistake on origin.Never do this on a merge commit however. Unless you are prepared: https://git-scm.com/blog/2010/03/02/undoing-merges.html
This is why rebase is so, so much better than merge. And it's infinitely better for bisecting, too.
Simple, completely linear history for origin/master is just so powerful in many that aspects that I'm constantly baffled why merging seems to be the flow mostly being talked about.
Now someone usually comes and says that merges are superior for long running branches. Which may be true in some aspects, but when you have more than one "running" branch and you got to try and find which commits have the code changes that only together seem to break and this is after 2 non-trivial merge commits, you really start to wish you'd gone with rebase.
Simple, completely linear history for origin/master is just so powerful in many that aspects that I'm constantly baffled why merging seems to be the flow mostly being talked about.
Now someone usually comes and says that merges are superior for long running branches. Which may be true in some aspects, but when you have more than one "running" branch and you got to try and find which commits have the code changes that only together seem to break and this is after 2 non-trivial merge commits, you really start to wish you'd gone with rebase.
For those of us who are uneducated / haven't seen this before: how do you use rebase to merge a separate branch? Are you suggesting you just `git rebase my-branch` from master / develop? How do you coordinate this with multiple team members. Merges appear to work better when you have multiple team members with separate feature branches that may have some overlap (conflicts may occur, but those can be handled as they arise).
First off, see [0] for a very helpful insight into the rebase command's syntax.
With multiple team members (each on their own feature branch), I encourage what I call the "pitchfork" approach [1], where the feature branches get stacked up into an integration branch to preview what the master branch would ultimately be when all the feature branches are merged in via pull requests.
A key part of building and recreating the pitchfork structure is git rerere [2].
[0] http://matthew-brett.github.io/pydagogue/rebase_without_tear...
[1] https://gist.github.com/dkaminski/c8e59221bea74ab1fea615a468...
[2] https://git-scm.com/blog/2010/03/08/rerere.html
With multiple team members (each on their own feature branch), I encourage what I call the "pitchfork" approach [1], where the feature branches get stacked up into an integration branch to preview what the master branch would ultimately be when all the feature branches are merged in via pull requests.
A key part of building and recreating the pitchfork structure is git rerere [2].
[0] http://matthew-brett.github.io/pydagogue/rebase_without_tear...
[1] https://gist.github.com/dkaminski/c8e59221bea74ab1fea615a468...
[2] https://git-scm.com/blog/2010/03/08/rerere.html
Hey @malingo, sorry I didn't reply to this immediately, but here are some of my initial thoughts. I apologize if this whole post sounds like a bit of a ramble, I'm writing this late in a train of thought. First thoughts:
1) git-rerere is really cool, and can probably make things very convenient, especially if you do several rebase operations to stack your integration branch. Without git-rerere, I can't imagine this workflow being remotely sane (resolving the same conflict every time you try to add an additional commit on one of the branches would get old fast).
2) This approach could probably help in "merging" (not git-merge, but you know) several feature branches with lots of conflicts, but does sort of rely on "As long as you make clean commits on the correct feature branches". While it's a laudable goal, how often can this really be the case, especially in projects where contributors are not composed of a single, core team (i.e. open source or research based projects)? I would think that ensuring clean commits is hard enough without a fixed team, so I am genuinely curious how hard it is to enforce this assumption.
See, here's the thing -> integration like this seems to work really well, especially if you're sharing branches across the repository with several teammates / coworkers. But what if you're not sharing branches? In the example you provided at [1], you have three branches: A, B, and C. Because you have access to all branches, it's easy to make an integration branch that does master -> Ai -> Bi -> Ci, and to handle all the conflicts with rerere. Then as A, B, C evolve and more commits are pushed, you could even have a build-bot of some sort assist in rebuilding the integration branch and checking for significant conflicts or errors. Of course, this all works great, but git is distributed.
What that means in practice is you may have master and branch A on your machine, and your two coworkers might have B and C on their machines, but none of you have rights to push these branches to the main repository location. This is common in BDFL-type projects, where one person or a handful of people are the only ones capable of pushing branches to the main repo. If your organization is split up like this, and individual developers tend to work on fixing single issues at a time, then you really never get the opportunity to use the integration branches, since you're only ever integrating your own (single) branch! If there's a bottleneck on upstream whatsoever, then the difference between this model and merging isn't really apparent, as you're not really getting any benefit either way (rebase -i non-withstanding). It would seem this would just kick the can down the road for the next developer to rebase off of the new master (with A rebased/merged in) and then solve their problems locally. This could be a significant duplication of effort if handled poorly.
I suppose you could have an intermediate "integration" repo where everyone pushes their branches, and build this sort of setup in assistance with some sort of CI, but I wonder how that scales if you have > 20 issue branches. The reason I ask this is because in the pitchfork workflow, how do you know which branch gets integrated first, second, etc.? I'm sure there's somewhat of a natural ordering in practice, as some issues or features probably take priority over others for some reason or another, but what if you don't know? What's the best way to keep the history? Certainly history isn't everything, but you may want to bisect down the road and A -> B -> C may cause more problems than B -> C -> A (you might not know at this point in time). Furthermore, do you not need someone / several people working together to resolve these conflicts? Is it sane to keep bothering your coworkers with "hey I just made a new integration branch, what do I do about conflict X", while they're still pushing new commits to B or C?
I think the pitchfork strategy for rebasing onto master is intriguing, and I'd have to play with it for an extended period of time to really get answers to some of these questions. Unfortunately, it seems that the bottleneck issue isn't something that can be easily solved for most projects. I don't come across many projects that allow every contributor to push branches, especially if they allow for pull-requests of any kind (even for one-off contributions). Nonetheless, I've definitely learned something here, and I think I understand better why one might want to rebase instead of merge. Then again, pull-requests are very heavily tied to merge-based flows, and if the project I'm contributing to wants to use them, then I'm probably hooped to begin with. Git is great for letting teams decide how they want to work, but it can be very painful if even one contribution doesn't follow guidelines (both to break a consistent history / commit graph, as well as if you ever have to git-bisect over it).
[1] https://gist.github.com/dkaminski/c8e59221bea74ab1fea615a468...
1) git-rerere is really cool, and can probably make things very convenient, especially if you do several rebase operations to stack your integration branch. Without git-rerere, I can't imagine this workflow being remotely sane (resolving the same conflict every time you try to add an additional commit on one of the branches would get old fast).
2) This approach could probably help in "merging" (not git-merge, but you know) several feature branches with lots of conflicts, but does sort of rely on "As long as you make clean commits on the correct feature branches". While it's a laudable goal, how often can this really be the case, especially in projects where contributors are not composed of a single, core team (i.e. open source or research based projects)? I would think that ensuring clean commits is hard enough without a fixed team, so I am genuinely curious how hard it is to enforce this assumption.
See, here's the thing -> integration like this seems to work really well, especially if you're sharing branches across the repository with several teammates / coworkers. But what if you're not sharing branches? In the example you provided at [1], you have three branches: A, B, and C. Because you have access to all branches, it's easy to make an integration branch that does master -> Ai -> Bi -> Ci, and to handle all the conflicts with rerere. Then as A, B, C evolve and more commits are pushed, you could even have a build-bot of some sort assist in rebuilding the integration branch and checking for significant conflicts or errors. Of course, this all works great, but git is distributed.
What that means in practice is you may have master and branch A on your machine, and your two coworkers might have B and C on their machines, but none of you have rights to push these branches to the main repository location. This is common in BDFL-type projects, where one person or a handful of people are the only ones capable of pushing branches to the main repo. If your organization is split up like this, and individual developers tend to work on fixing single issues at a time, then you really never get the opportunity to use the integration branches, since you're only ever integrating your own (single) branch! If there's a bottleneck on upstream whatsoever, then the difference between this model and merging isn't really apparent, as you're not really getting any benefit either way (rebase -i non-withstanding). It would seem this would just kick the can down the road for the next developer to rebase off of the new master (with A rebased/merged in) and then solve their problems locally. This could be a significant duplication of effort if handled poorly.
I suppose you could have an intermediate "integration" repo where everyone pushes their branches, and build this sort of setup in assistance with some sort of CI, but I wonder how that scales if you have > 20 issue branches. The reason I ask this is because in the pitchfork workflow, how do you know which branch gets integrated first, second, etc.? I'm sure there's somewhat of a natural ordering in practice, as some issues or features probably take priority over others for some reason or another, but what if you don't know? What's the best way to keep the history? Certainly history isn't everything, but you may want to bisect down the road and A -> B -> C may cause more problems than B -> C -> A (you might not know at this point in time). Furthermore, do you not need someone / several people working together to resolve these conflicts? Is it sane to keep bothering your coworkers with "hey I just made a new integration branch, what do I do about conflict X", while they're still pushing new commits to B or C?
I think the pitchfork strategy for rebasing onto master is intriguing, and I'd have to play with it for an extended period of time to really get answers to some of these questions. Unfortunately, it seems that the bottleneck issue isn't something that can be easily solved for most projects. I don't come across many projects that allow every contributor to push branches, especially if they allow for pull-requests of any kind (even for one-off contributions). Nonetheless, I've definitely learned something here, and I think I understand better why one might want to rebase instead of merge. Then again, pull-requests are very heavily tied to merge-based flows, and if the project I'm contributing to wants to use them, then I'm probably hooped to begin with. Git is great for letting teams decide how they want to work, but it can be very painful if even one contribution doesn't follow guidelines (both to break a consistent history / commit graph, as well as if you ever have to git-bisect over it).
[1] https://gist.github.com/dkaminski/c8e59221bea74ab1fea615a468...
Yes, just rebase your whole feature branch on top of origin/master. Long-running branches with huge amounts of commits are bad anyway for multiple reasons, so it's not like you're bringing too many commits at once with any given rebase.
I'm not sure why you think this is worse to coordinate than merge commits? I think encouraging rebase-heavy workflow where feature branches are put into origin/master as often as possible actually improves the coordination quite a lot. When working that way, origin/master is always pretty recent, and anyone starting a new feature branch from top of it has really small risk of missing any big change sets from coworkers. On the other hand, I feel that merge-heavy workflow encourages people to have long-running branches other than origin/master, which hides commits from others.
I'm not sure why you think this is worse to coordinate than merge commits? I think encouraging rebase-heavy workflow where feature branches are put into origin/master as often as possible actually improves the coordination quite a lot. When working that way, origin/master is always pretty recent, and anyone starting a new feature branch from top of it has really small risk of missing any big change sets from coworkers. On the other hand, I feel that merge-heavy workflow encourages people to have long-running branches other than origin/master, which hides commits from others.
[deleted]
If you're concerned about not knowing how to do certain things with git, and understanding at a deeper level how git works, I highly recommend reading Scott Chacon's "Pro Git" book:
https://progit.org/
https://progit.org/
I second your recommendation, this book has saved my bacon multiple times.
But does anyone know why this project has two homes?
https://git-scm.com/book/en/v2
But does anyone know why this project has two homes?
https://git-scm.com/book/en/v2
My understanding is that the dedicated site above highlights the book itself, while git-scm.com recommends/promotes the book.
That book is great, and so is the built-in gittutorial(7). If you really want to get down and dirty with Git, I'd also strongly recommend going one step further and reading gitcore-tutorial(7). It shows you the man behind the memorized commands curtain.
[deleted]
Seconded.
Also, I think everyone should go through Neo's Git Immersion at some point early in their experience with git. It is the best crash course by far.
Also, I think everyone should go through Neo's Git Immersion at some point early in their experience with git. It is the best crash course by far.
With all these recipies - one thing I do whenever I attempt some stunt in git: I assign temporary tags to every changeset that's important.
And to be aware what happens, there one single explanation of git that helps a lot: http://eagain.net/articles/git-for-computer-scientists/
As soon as you start viewing git as a graph of nodes with branches/tags just being "marked" nodes a lot of things make sense, and whatever "git perform-stunt" you attempt it's easy to explain within that mental model.
git tag tmp
git perform-stunt
This eases undoing the stunt without needing to find the "before" state from reflog. And if you use a graphical log viewer (I like SourceTree on Mac) you'll see the tagged state in the history view - which makes things a lot clearer.And to be aware what happens, there one single explanation of git that helps a lot: http://eagain.net/articles/git-for-computer-scientists/
As soon as you start viewing git as a graph of nodes with branches/tags just being "marked" nodes a lot of things make sense, and whatever "git perform-stunt" you attempt it's easy to explain within that mental model.
http://www.robertames.com/blog.cgi/entries/git-in-two-ten-mi... ... feedback welcome, but I feel like I go into a bit more depth using similar metaphors.
The last addendum reminds me of this inexorably relevant xkcd entry: https://xkcd.com/1597/
> Oh shit, I accidentally committed to the wrong branch!
Other ways to do it (that don't require to retype the commit message): - rebase onto the correct branch:
You probably want to know `git diff HEAD` too.
Edit: formatting.
Other ways to do it (that don't require to retype the commit message): - rebase onto the correct branch:
git branch foo
git reset --hard HEAD~
git rebase --onto name-of-the-correct-branch HEAD foo
git checkout name-of-the-correct-branch
git merge foo
git branch -D foo
- cherry-pick git reset --hard HEAD~
git checkout name-of-the-correct-branch
git cherry-pick name-of-the-branch-you-mistakenly-committed-to@{1} (or git cherry-pick HEAD@{2})
> Oh shit, I tried to run a diff but nothing happened?!You probably want to know `git diff HEAD` too.
Edit: formatting.
Or use git branch -m to rename master to something else, then checkout master anew.
for the first one, you don't need rebase afaik:
git branch name-of-the-correct-branch
git reset --hard HEAD~
git checkout name-of-the-correct-branchSurprised there was nothing on messed-up merges or rebases. They're some of the worst to get out of when you're not totally comfortable with git yet.
And reflog. It sort of like revision control of your branches and commands. Very useful to extricate oneself from various situations.
+100 for reflog. Even for the stupidest cross-merges I've broken reflog has been my savior.
https://git-scm.com/docs/git-reflog
https://git-scm.com/docs/git-reflog
Any points on how to continue from there? Been in a few "I give up" conditions during rebases that I completely stopped trusting git it any way.
The thing is, some repositories on github require you to commit only after proper rebasing. But I can never in my life remember how and need to google it...
The thing is, some repositories on github require you to commit only after proper rebasing. But I can never in my life remember how and need to google it...
To abort a screwed up merge:
git merge --abort
To abort a screwed up rebase: git rebase --abort
Both of these will take you back to immediately before you began the operation.> Been in a few "I give up" conditions during rebases that I completely stopped trusting git it any way.
Been there too, with the same result.
> Any points on how to continue from there?
Honestly? Not always from the command-line, unfortunately. Basically, I just don't know the right commands to type on the command-line for everything I do with git, and it's not necessarily easy to find them either. I use the TortoiseGit GUI, and over there, it's a LOT more easy to see what is going on and to abort or continue rebases/merges as necessary, or to do fancier stuff. But the thing is, because I understand git and I know what should logically happen at every step, I can cherry-pick commits, revert them, abort/continue merges, rebase commits, or do whatever else the heck I want without getting into trouble anymore... even though I don't know how to do many of them on the command line.
Of course, it took a lot of suffering to get here. Starting with the GUI would of course be the wrong approach. But once you've understood what's going on, then I would recommend you entirely ditch the command line and switch to something like TortoiseGit (I hope you're either on Windows or your platform has something as good as that). The GUI actually shows you what your options are at every step, so you don't have to know all the valid commands at every possible state. You just need to know what effect you need to cause.
Been there too, with the same result.
> Any points on how to continue from there?
Honestly? Not always from the command-line, unfortunately. Basically, I just don't know the right commands to type on the command-line for everything I do with git, and it's not necessarily easy to find them either. I use the TortoiseGit GUI, and over there, it's a LOT more easy to see what is going on and to abort or continue rebases/merges as necessary, or to do fancier stuff. But the thing is, because I understand git and I know what should logically happen at every step, I can cherry-pick commits, revert them, abort/continue merges, rebase commits, or do whatever else the heck I want without getting into trouble anymore... even though I don't know how to do many of them on the command line.
Of course, it took a lot of suffering to get here. Starting with the GUI would of course be the wrong approach. But once you've understood what's going on, then I would recommend you entirely ditch the command line and switch to something like TortoiseGit (I hope you're either on Windows or your platform has something as good as that). The GUI actually shows you what your options are at every step, so you don't have to know all the valid commands at every possible state. You just need to know what effect you need to cause.
If you ever get yourself in a situation during a rebase, or find that a rebase went wrong, have a look at `git reflog`.
Running it gives you a log of all the things `HEAD` has ever pointed at, meaning you can find what you had before a rebase and check that out.
Running it gives you a log of all the things `HEAD` has ever pointed at, meaning you can find what you had before a rebase and check that out.
git reflog
git checkout HEAD@{10}
And you're usually good to go.> Been in a few "I give up" conditions during rebases that I completely stopped trusting git it any way.
People use rebase in a far too casual way. Rebasing is a pretty advanced use case, one that is unnecessary for normal git usage. You sentence sounds like: I stopped trusting Ford because the car stopped working when I reprogrammed the ECU.
In short: If you are not entirely comfortable with git's inner workings, do not use rebase. Do not complain if you shoot yourself the foot with rebase.
People use rebase in a far too casual way. Rebasing is a pretty advanced use case, one that is unnecessary for normal git usage. You sentence sounds like: I stopped trusting Ford because the car stopped working when I reprogrammed the ECU.
In short: If you are not entirely comfortable with git's inner workings, do not use rebase. Do not complain if you shoot yourself the foot with rebase.
'sudo rmdir'? I don't think that does what they think it does.
For posterity, `rmdir` will only remove empty directories. The author presumably should have used `rm -rf`.
I think the command we're looking for is 'rm -R name_of_directory'
At least in GNU rm, -R and -r are synonymous. -f suppresses all prompts ("remove write-protected file ...?"), so the parent is also correct :)
Need to use `-f` when dealing with git repositories unfortunately.
Honestly, the proper command is not rm at all, because you can then have an "oh shit I forgot something" moment. I have learned (the hard way) to retain even an horribly broken repo, but shove it out of the way. Because disk is cheap, repeating work is expensive.
So that example should have been:
So that example should have been:
cd ..
mv fucking-git-repo-dir fucking-git-repo-dir.archived.$(date +%s)
git clone https://some.github.url/fucking-git-repo-dir.git git fetch origin master && git reset --hard origin/master
imoOr maybe
sudo rm -rf /some/path --no-preserve-root[deleted]
Based on the article, and many of the comments here, I didn't realise how comfortable I have become using git!
For example, the last "bad situation" I had to get myself out of involved unreadable .git contents caused by filesystem corruption. If you can "rm -rf fucking-git-repo-dir" then it's not too bad; when that fails with an IO error is when things get interesting!
For example, the last "bad situation" I had to get myself out of involved unreadable .git contents caused by filesystem corruption. If you can "rm -rf fucking-git-repo-dir" then it's not too bad; when that fails with an IO error is when things get interesting!
I really like this article but there is a problem with it: what happens if I use one of your techniques and I screw up? These steps you describe are a black box to someone who is no git savvy yet. While these definitely help but they propagate the "git is scary, cross your fingers" mentality. What I mean by this is that the reader won't be any wiser after reading
> git reset HEAD~ --hard
What is ~ after HEAD? What is --hard? Is there a --deep option as well?
So I think that you could upgrade this with some annotations over the cryptic parts with a little explanation. What do you think?
> git reset HEAD~ --hard
What is ~ after HEAD? What is --hard? Is there a --deep option as well?
So I think that you could upgrade this with some annotations over the cryptic parts with a little explanation. What do you think?
On the other hand all of these options are well documented in the git book and manual, so it's quite easy to check the details you're not sure about (and learn something new in the process).
After all this time the HEAD~ syntax has suddenly started making sense to me -- this is the syntax for backup files in vim, so HEAD~ is the "backup" i.e. previous version of HEAD.
Doing mumbo-jumbo between branches with `git stash` is way to hell. Don't do it, you lose data. This fucker will unstash changes until first conflict, then it stop and present you with <<<<<<<ID and >>>>>>>ID which nobody understand.
Well I understand it, but never know which is which (theirs/ours label don't help here). You try to undo everything, but then you're fucked - all unstashed changes are removed from stash while conflicts are still there. You must be very careful now not to lose changes. You won't succeed!
That is I believe `git stash` should be removed from git as evil data loosing feature, not needed. Instead just make an alias `git save <TEMP_BRANCH_NAME>` which saves your temporary work to the branch:
`save = !sh -c 'export PREV=$(git symbolic-ref HEAD|cut -d/ -f3-) && git checkout -b "$1" && git commit -am "$1" && git checkout "$PREV"' -`
That is I believe `git stash` should be removed from git as evil data loosing feature, not needed. Instead just make an alias `git save <TEMP_BRANCH_NAME>` which saves your temporary work to the branch:
`save = !sh -c 'export PREV=$(git symbolic-ref HEAD|cut -d/ -f3-) && git checkout -b "$1" && git commit -am "$1" && git checkout "$PREV"' -`
You can use `git stash apply` to apply the stashed changes without removing them from the stash.
From man git-stash:
"Applying the state can fail with conflicts; in this case, it is not removed from the stash list. You need to resolve the conflicts by hand and call git stash drop manually afterwards."
Or do I misunderstand you?
"Applying the state can fail with conflicts; in this case, it is not removed from the stash list. You need to resolve the conflicts by hand and call git stash drop manually afterwards."
Or do I misunderstand you?
[deleted]
Actually the easiest thing is simply not to care about how your log looks.
If you don't then there are ry only two things you need to know how to do:
If you didn't push to origin do an ammend. If you did, revert soft and commit the previous code to revert it (you can also put a stash or patch to apply it back).
Which frankly is what the article does, basically.
If you don't then there are ry only two things you need to know how to do:
If you didn't push to origin do an ammend. If you did, revert soft and commit the previous code to revert it (you can also put a stash or patch to apply it back).
Which frankly is what the article does, basically.
> Actually the easiest thing is simply not to care about how your log looks.
You need to expand on this because i don't quite understand what you mean, are you talking about "fix typo" commits or are we getting to the level of just committing away until things work and then not cleaning up the work later on? The linked article doesn't cover rebasing or squashing commits, which can be pretty powerful when used correctly.
Your commit log is the one thing that is immutably linked to your code changes. Your documentation isn't, the comments in your code aren't, you will forget why you made a change, anyone reviewing your logs needs to understand your intention, your bug tracker will probably change several times over the life of a project, and so on. So, make an effort to have a commit log that is clean and comprehensive and commits that don't break tests.
I go into this in more detail in a talk i gave last week: https://www.youtube.com/watch?v=9OHAq8dCoS4
You need to expand on this because i don't quite understand what you mean, are you talking about "fix typo" commits or are we getting to the level of just committing away until things work and then not cleaning up the work later on? The linked article doesn't cover rebasing or squashing commits, which can be pretty powerful when used correctly.
Your commit log is the one thing that is immutably linked to your code changes. Your documentation isn't, the comments in your code aren't, you will forget why you made a change, anyone reviewing your logs needs to understand your intention, your bug tracker will probably change several times over the life of a project, and so on. So, make an effort to have a commit log that is clean and comprehensive and commits that don't break tests.
I go into this in more detail in a talk i gave last week: https://www.youtube.com/watch?v=9OHAq8dCoS4
Develop on feature branches, merge with master only when the feature is done. Always merge with --no-ff. Then, when reviewing history, on the master branch you can use either "git log" or "git log --first-parent master". The first log is the complete log, with exploratory development, mistakes, backtracks and such. The second is the clean log people keep rewriting history to obtain.
You get your cake and you can eat it too.
You get your cake and you can eat it too.
This is pretty much the reason i don't understand people who don't want merge commits (the use case for rebase in the video is modifying commits in a feature branch BTW, not merging to master). You can bend git logs to your will with the various options so there's no problem in being as verbose as possible in commit messages and the concept of a "linear history" is a moot point because, no matter how messy your history actual is, there's a command line option to clear it up.
Be verbose in your commit messages and don't worry about merge commits, it will pay dividends later.
Be verbose in your commit messages and don't worry about merge commits, it will pay dividends later.
> Actually the easiest thing is simply not to care about how your log looks.
Yes, that sounds as easy as anything that accepts the idea of "let's do this the shitty-but-quick way now, and pay the technical debt later". So yes, it is "easier" to work with in the beginning.
On the other hand, if I had to inherit your repository that was developed by "not caring about history", I would probably have to hunt you down and kill you. So there's that.
Yes, that sounds as easy as anything that accepts the idea of "let's do this the shitty-but-quick way now, and pay the technical debt later". So yes, it is "easier" to work with in the beginning.
On the other hand, if I had to inherit your repository that was developed by "not caring about history", I would probably have to hunt you down and kill you. So there's that.
On the other hand, if I had to inherit your repository that was developed by "not caring about history", I would probably have to hunt you down and kill you. So there's that.
Yep. Some people just want to keep taking technical debt on (read: hack-it-'till-it-works), which makes them likely candidates for a good thrashing in some dark blind street in the middle of the night. And some don't even get it after that. Actually, now that you made me think about it, most people in this industry aren't really computer people material, that's the problem.
Yep. Some people just want to keep taking technical debt on (read: hack-it-'till-it-works), which makes them likely candidates for a good thrashing in some dark blind street in the middle of the night. And some don't even get it after that. Actually, now that you made me think about it, most people in this industry aren't really computer people material, that's the problem.
Having a messy and complex git log is not only about the visuals though. It can make it a lot harder to track down when/where/why bugs and problematic code was introduced. It makes both git bisect and git blame less useful.
Exactly. The canonical reference to how a git log should look is the Linux kernel, since git was written for it: https://github.com/torvalds/linux/commits/master Bisect and blame are amazing in that repo.
lots of these are unnecessarily complicated:
> Oh shit, I accidentally committed something to master that should have been on a brand new branch!
first, you don't need to git-add before and after stash, stash will save the working directory and the index (as documented in the DESCRIPTION of git-stash(1)). but for a more logical way:
> Oh shit, I accidentally committed something to master that should have been on a brand new branch!
# disappear the last commit and all changes from it
git reset --hard HEAD^
# make a new branch using the last commit
git checkout -b new-branch HEAD@{1}
> Oh shit, I accidentally committed to the wrong branch!first, you don't need to git-add before and after stash, stash will save the working directory and the index (as documented in the DESCRIPTION of git-stash(1)). but for a more logical way:
# disappear the last commit and all changes from it
git reset --hard HEAD^
# get onto the new branch
git checkout new-branch
# grab the stuff from what was on the old branch
git cherry-pick old-branch@{1}
> Oh shit, I tried to run a diff but nothing happened?! git diff --cached
recommended reading for intermediate git users: the DESCRIPTIONs of all of these commands (git-reset(1), git-checkout(1), git-cherry-pick(1), git-diff(1)), and the entirety of gitrevisions(7).Getting to "Fuck this noise, I give up." is a very clear indication that you aren't competent enough and you should take a GOOD course about git as soon as humanly possible.
Shameless plug: http://engineering.hipolabs.com/how-to-work-in-a-team-versio...
Shameless plug: http://engineering.hipolabs.com/how-to-work-in-a-team-versio...
> Getting to "Fuck this noise, I give up." is a very clear indication that you aren't competent enough
I think that's a tad judgemental for two reasons:
1- because git is legitimately hard to learn. Personally I suspect git is unnecessarily hard to learn, that command names and the concepts and workflows I need are possible to learn and use with less effort. For many years people around me have been asking for git help because I know how to recover from lost stashes and use the reflog, etc., and yet I still have to google the magic incantations for commands I use regularly because they're impossible to remember.
2- There is actually a lot of value in being able to spin up a new repo instantly, in knowing that you can, and in practicing it often. Not unlike the move to VMs for development environments. Plus, there are definitely bad situations where a fresh git clone is the simpler way to go -- just not in this article. ;)
Anyway, I also agree with you because this blog post doesn't describe any truly bad situations, and because for years I've seen people blowing away their repos and starting over, and always thought to myself it was funny. It's a drastic action that takes more work than a rebase or reflog or whatever the problem was, and doesn't work well if you've made changes.
I think that's a tad judgemental for two reasons:
1- because git is legitimately hard to learn. Personally I suspect git is unnecessarily hard to learn, that command names and the concepts and workflows I need are possible to learn and use with less effort. For many years people around me have been asking for git help because I know how to recover from lost stashes and use the reflog, etc., and yet I still have to google the magic incantations for commands I use regularly because they're impossible to remember.
2- There is actually a lot of value in being able to spin up a new repo instantly, in knowing that you can, and in practicing it often. Not unlike the move to VMs for development environments. Plus, there are definitely bad situations where a fresh git clone is the simpler way to go -- just not in this article. ;)
Anyway, I also agree with you because this blog post doesn't describe any truly bad situations, and because for years I've seen people blowing away their repos and starting over, and always thought to myself it was funny. It's a drastic action that takes more work than a rebase or reflog or whatever the problem was, and doesn't work well if you've made changes.
1- That's certainly true, git is really hard to learn. But if you're a developer it's worth getting comfortable with it, which means not going for the "nuclear option" every time something weird happens. Someone on StackOverflow has had your problem, and has the perfect fix, look that up instead.
2- Yes, absolutely, it's good to remember that it's a fairly painless and easy process to spin up fresh clones. Though, if all you want is a fresh copy, in 99% of cases a "git clean -xfd" will do that for you (read the man page to find out what the options mean! man pages are your friend!). Though that one is generally a "pull ripcord in case of emergency" type of command, "git stash" generally suffices and avoids risk of losing data.
2- Yes, absolutely, it's good to remember that it's a fairly painless and easy process to spin up fresh clones. Though, if all you want is a fresh copy, in 99% of cases a "git clean -xfd" will do that for you (read the man page to find out what the options mean! man pages are your friend!). Though that one is generally a "pull ripcord in case of emergency" type of command, "git stash" generally suffices and avoids risk of losing data.
I totally agree, git is worth learning.
I don't recommend git stash, it frequently causes bad situations. Just branch instead, branching is safer and just as easy as stashing. Stash is not as safe as other git commands. From the man page: "If you mistakenly drop or clear stashes, they cannot be recovered through the normal safety mechanisms."
I don't recommend git stash, it frequently causes bad situations. Just branch instead, branching is safer and just as easy as stashing. Stash is not as safe as other git commands. From the man page: "If you mistakenly drop or clear stashes, they cannot be recovered through the normal safety mechanisms."
If the "right" solution is more difficult, and no more effective than fucking this noise, then in what sense is it even desirable or good to use the "right" solution? How is it more right?
I think the nuclear option is pretty nice, since it solves every git problem I've ever heard of. All the "right" solutions only solve some particular slice of cases. Why should I be bothered to care?
I think the nuclear option is pretty nice, since it solves every git problem I've ever heard of. All the "right" solutions only solve some particular slice of cases. Why should I be bothered to care?
Totally depends on the situation, but it's uncommon for nuke to be easier and more effective than fixing things using a rebase. Specifically, all of the examples in the blog post are easier to solve with the right git command than they are with a nuke & re-clone.
There's a class of bad situations that nuke will make worse and not better. Any time you have un-pushed work, you're better off figuring out how to restore it with proper git commands than by nuking your repo. Dropped stashes or screwed up merges or rebase mistakes are all things that take some unavoidable time to learn how to fix.
There's a class of bad situations that nuke will make worse and not better. Any time you have un-pushed work, you're better off figuring out how to restore it with proper git commands than by nuking your repo. Dropped stashes or screwed up merges or rebase mistakes are all things that take some unavoidable time to learn how to fix.
If we had to take a GOOD course in every tool that can be used when writing software then we'd have no time to, you know, write software.
Not all people who write software are full-time developers. Not all people who use git are developers at all, come to mention it. Not all people who use git for one thing use it for everything. Not everyone can justify the time required for a course for something that might be a tiny part of their work.
Not all people who write software are full-time developers. Not all people who use git are developers at all, come to mention it. Not all people who use git for one thing use it for everything. Not everyone can justify the time required for a course for something that might be a tiny part of their work.
Most of the problems can be solved easily if this is understood - Quote from that article - "Absorb that, internalise it, make it your mantra for the rest of your life or career: a git repository is a tree. "
This doesn't even cover half of the bad situations I've gotten myself in over the last few years :D
Long term, it's best to thouroughly read the man pages, e.g. nicely formatted here: https://git-scm.com/docs
Long term, it's best to thouroughly read the man pages, e.g. nicely formatted here: https://git-scm.com/docs
Another option is to use Mercurial with hg-git to GitHub for network effects.
I've been doing that for a while for dropbear ssh, it does hit occasional problems but is overall more pleasant than straight git.
I've been doing that for a while for dropbear ssh, it does hit occasional problems but is overall more pleasant than straight git.
To each his own, of course. As a Git aficionado, I find Mercurial utterly baffling. Branches are permanent and global? You have to clone the repo to make a new thing I would call a branch? "hg log" shows you things that are not in the history of your current source tree? Mind boggling.
:)
:)
I've had problems with tags. What else have caused you problems?
Mainly when I've merged a pull request on github, didn't pull to mercurial, then did some branching in mercurial. Eventually have always managed to sort it out, but sometimes requires a bit of push/pull fiddling.
Now you mention it my git tags are out of date...
Now you mention it my git tags are out of date...
There is no substitute for understanding what's going on, especially using a power tool like Git.
It's a cute website, and useful, I really like it. This sentence,
It's a cute website, and useful, I really like it. This sentence,
Bizarrely, git won't do a dif of files that have
been add-ed to your staging area without this flag.
File under ¯\_(ツ)_/¯"
just screams to me (a professional Git trainer), "I don't understand the Git staging area! I don't know my Git fundamentals! Train me!"For people wondering about this:
Add --cached or --staged (synonyms) to scope to the staging area.
Any resources you recommend for learning git in more detail?
1. Our "Git Fundamentals: Basic Concepts and Definitions" webinar, http://www.verticalsysadmin.com/git/ (you have to register) lays the groundwork you need to start studying Git.
If you have a team that needs Git training, email me and we can deliver a instance of this webinar (complete with Q&A session) free of charge (as an introductory service).
2. For someone just starting out, I also recommend "Learn Enough Git to be Dangerous", https://www.learnenough.com/git-tutorial (HTML version available for free), from @mhartl, author of the popular RailsTutorial.org
3. The "Pro Git" book is great. https://git-scm.com/book/en/v2 A comprehensive resource.
If you have a team that needs Git training, email me and we can deliver a instance of this webinar (complete with Q&A session) free of charge (as an introductory service).
2. For someone just starting out, I also recommend "Learn Enough Git to be Dangerous", https://www.learnenough.com/git-tutorial (HTML version available for free), from @mhartl, author of the popular RailsTutorial.org
3. The "Pro Git" book is great. https://git-scm.com/book/en/v2 A comprehensive resource.
I don't know if this post was intended as humour or a way to vent out some frustration but in my experience, this path of treating git as "spell X solves problem Y" will always break down.
Version control systems are an important part of the programmers toolkit and it's worth investing a little time to get the fundamentals right.
Sure git is not the friendliest of beasts but what it lacks in interface, it more than makes up in internal consistency and trying to learn it "inside out" is a better long term investment than having a list of ways to solve "git problems".
Version control systems are an important part of the programmers toolkit and it's worth investing a little time to get the fundamentals right.
Sure git is not the friendliest of beasts but what it lacks in interface, it more than makes up in internal consistency and trying to learn it "inside out" is a better long term investment than having a list of ways to solve "git problems".
I think the biggest problem people have with git is that you can't and shouldn't want to change shared history, and yet git provides some tools that suggest that maybe you can.
It's better to accept history as it is, and fix the problem with reverts, cherry-picking and new commits. History won't be as pretty or clean, but it will reflect what actually happened, which is what history is, after all.
The biggest trick to understanding git is to learn to think in commits rather than file content. If one branch has a commit and the other branch doesn't, merging them will mean that the commit is there. If one branch has the commit while the other branch has the commit and a revert for that commit, merging will mean it will be reverted.
Same goes with pushing. If you reset locally to before a commit that you already shared, that commit returns on your next pull. If you revert it, it will stay reverted.
The most dangerous thing git can do, is rebasing. Rebase changes history. This is fine if it hasn't been shared yet (you commited a new change and try to push, but remote changes need to be pulled first, so rebasing is fine). Rebasing is not fine if the commit has already been shared, through a different branch or a different remote repository, for example. In that case, you need a merge.
As pretty as rebase can make your history, you should really only use it when you understand what it does. If you don't, stick with merge.
It's better to accept history as it is, and fix the problem with reverts, cherry-picking and new commits. History won't be as pretty or clean, but it will reflect what actually happened, which is what history is, after all.
The biggest trick to understanding git is to learn to think in commits rather than file content. If one branch has a commit and the other branch doesn't, merging them will mean that the commit is there. If one branch has the commit while the other branch has the commit and a revert for that commit, merging will mean it will be reverted.
Same goes with pushing. If you reset locally to before a commit that you already shared, that commit returns on your next pull. If you revert it, it will stay reverted.
The most dangerous thing git can do, is rebasing. Rebase changes history. This is fine if it hasn't been shared yet (you commited a new change and try to push, but remote changes need to be pulled first, so rebasing is fine). Rebasing is not fine if the commit has already been shared, through a different branch or a different remote repository, for example. In that case, you need a merge.
As pretty as rebase can make your history, you should really only use it when you understand what it does. If you don't, stick with merge.
`git rebase -i` by default rebases only back to the first commit you haven't shared (at least that's how I interpret the actual behaviour). This is a great default - it's the simplest way to change history and at the same time powerful without being too dangerous.
Ah, interesting. I'd noticed this behaviour but hadn't conciously thought about it.
The docs say:
All changes made by commits in the current branch but that are not in <upstream> are saved to a temporary area. This is the same set of commits that would be shown by git log <upstream>..HEAD
The docs say:
All changes made by commits in the current branch but that are not in <upstream> are saved to a temporary area. This is the same set of commits that would be shown by git log <upstream>..HEAD
If they're not in upstream but they are in another branch, it's still dangerous.
I think the ability to edit history is one of the great advantages of Git. I encourage people to use it rather than ignore it.
Cleaner history makes life much easier for those who will try to understand what you did weeks or months or even years later (including your future self).
Of course, you shouldn't (with rare exceptions) edit history you have already shared with others; but, I never found that concept, or the way git implements it, particularly hard to understand. (I will admit some of git's commands are hard to remember - I am always forgetting the difference between "git reset --hard" and "git reset --soft".)
Cleaner history makes life much easier for those who will try to understand what you did weeks or months or even years later (including your future self).
Of course, you shouldn't (with rare exceptions) edit history you have already shared with others; but, I never found that concept, or the way git implements it, particularly hard to understand. (I will admit some of git's commands are hard to remember - I am always forgetting the difference between "git reset --hard" and "git reset --soft".)
> but it will reflect what actually happened, which is what history is, after all.
Recorded history is not necessarily what actually happened though, often (or always, according to some) it's an interpretation.
"History is written by the victors" - Walter Benjamin?
Recorded history is not necessarily what actually happened though, often (or always, according to some) it's an interpretation.
"History is written by the victors" - Walter Benjamin?
> I think the biggest problem people have with git is that you can't and shouldn't want to change shared history, and yet git provides some tools that suggest that maybe you can.
Funny, I think the biggest problem is people who refuse to understand the caveats of rewriting shared history and spread FUD about it.
Funny, I think the biggest problem is people who refuse to understand the caveats of rewriting shared history and spread FUD about it.
> If one branch has a commit and the other branch doesn't, merging them will mean that the commit is there. If one branch has the commit while the other branch has the commit and a revert for that commit, merging will mean it will be reverted.
See, I fundamentally disagree that this is what I wanted. When I merge my thing with change x into head I expect to see my changes actually go in. Not to see commits retroactively added to head. The merge was the action, not some weird rewriting of historical order of events.
> The biggest trick to understanding git is to learn to think in commits rather than file content.
Ok, I'm starting to see what you meant. (I didn't understand this until the second part and my being confused as heck)
See, I fundamentally disagree that this is what I wanted. When I merge my thing with change x into head I expect to see my changes actually go in. Not to see commits retroactively added to head. The merge was the action, not some weird rewriting of historical order of events.
> The biggest trick to understanding git is to learn to think in commits rather than file content.
Ok, I'm starting to see what you meant. (I didn't understand this until the second part and my being confused as heck)
"Not the friendliest of beasts" is putting it mildly.
Git is basically Linus in a nutshell: abrasive, unforgiving, and behaving like an absolute asshole to any non-expert struggling user.
Sure, engineers should probably get to know its quirks and learn to work around them because it's now ubiquitous in the field, but let's not pretend that there's something virtuous about it. This is a piece of truly terrible software with an even worse UX that just happened to win the PR battle against its superior foes, because...Idunno, Linux, I guess?
Git is basically Linus in a nutshell: abrasive, unforgiving, and behaving like an absolute asshole to any non-expert struggling user.
Sure, engineers should probably get to know its quirks and learn to work around them because it's now ubiquitous in the field, but let's not pretend that there's something virtuous about it. This is a piece of truly terrible software with an even worse UX that just happened to win the PR battle against its superior foes, because...Idunno, Linux, I guess?
> Git is basically Linus in a nutshell: abrasive, unforgiving, and behaving like an absolute asshole to any non-expert struggling user.
You forgot "brilliant".
You forgot "brilliant".
Fair point. For all my whining, I use both Git and Linux every day, they are incredible pieces of technology, especially compared to what came before.
not necessarily better than most other good engineers...
He knows a lot about his domain, sure, but he's no god and there are a lot of areas he knows diddley-squat about.... user interface design for one!
He knows a lot about his domain, sure, but he's no god and there are a lot of areas he knows diddley-squat about.... user interface design for one!
> He knows a lot about his domain, sure, but he's no god and there are a lot of areas he knows diddley-squat about.... user interface design for one!
And Einstein knew nothing about biology.
I'm sure he knows "diddley-squat" about most areas, but as long as he knows a lot about his domain then he's an expert.
And he is good at user interface design, and git is a good example of that; it's just not aimed at beginners. It was designed by and for expert users, and the interface fits that very well.
And Einstein knew nothing about biology.
I'm sure he knows "diddley-squat" about most areas, but as long as he knows a lot about his domain then he's an expert.
And he is good at user interface design, and git is a good example of that; it's just not aimed at beginners. It was designed by and for expert users, and the interface fits that very well.
no, its not a good UI.
admittedly "expert" UIs are different from "noob" UIs, but the number of "git magic spell" followers out there mean that it isn't a good UI for the majority of people who use git.
admittedly "expert" UIs are different from "noob" UIs, but the number of "git magic spell" followers out there mean that it isn't a good UI for the majority of people who use git.
Well, if you treat git as Torvalds intended it in the beginning (framework for
building VCS-es) and accordingly limit the discussion to git's plumbing
command set, you get a sensibly good UI+architecture that is targeted at
programmers that write VCS-es.
Git being operable with a pry bar and repairable with a hammer is a good proof that in this context it's a good design.
Git being operable with a pry bar and repairable with a hammer is a good proof that in this context it's a good design.
I'm not sure why a kernel developer would need to concern themselves with UI design?
Hah, so just like git then.
I'm struggling to see which VCS you deem superior, I'm assuming you are not referring to SVN, Mercurial maybe?
The learning curve to git is not great but as far as I know nobody has publicly released an option that's improved enough over git to motivate the cost of switching technology. If it's not working for you the only advice I can give is either learn it until it is actually working for you rather than being in the way or try to find a better workflow.
The learning curve to git is not great but as far as I know nobody has publicly released an option that's improved enough over git to motivate the cost of switching technology. If it's not working for you the only advice I can give is either learn it until it is actually working for you rather than being in the way or try to find a better workflow.
Yep, Mercurial's the one. It's a shame that it lost the war, they actually seemed to care about providing a good experience to their users. There are, of course, a few technical differences between it and git, but I personally never felt like they were troublesome enough to make up for the vast difference in usability.
I think Mercurial hasn't lost it yet. I speak as a creator of Mercurial Source Code management system (RhodeCode)
We see that a lot of companies(our clients/users) adopting Mercurial, you just don't hear about it. Often those are companies with employees that don't tweet or post to HN ;)
RhodeCode is used also in around 60 universities, and we learned that in a lot of them they teach Mercurial as well as Git.
For a large company it's actually much cheaper to adapt Mercurial as they new DVCS because of learning curve.
I hope companies like Facebook and Mozilla will make soon Mercurial very very fast. There's constant work on it coming from those companies to improve it.
We see that a lot of companies(our clients/users) adopting Mercurial, you just don't hear about it. Often those are companies with employees that don't tweet or post to HN ;)
RhodeCode is used also in around 60 universities, and we learned that in a lot of them they teach Mercurial as well as Git.
For a large company it's actually much cheaper to adapt Mercurial as they new DVCS because of learning curve.
I hope companies like Facebook and Mozilla will make soon Mercurial very very fast. There's constant work on it coming from those companies to improve it.
I don't think hg is going anywhere, if CVS is still alive and kicking in 2016, and especially since Facebook's using it. However, IMO hg lost when even python switched to git.
SVN is much easier to use for the standard corporate workflow of a group of people making commits to a project which mostly advances monotonically with continuous integration.
Edit: also in a Windows environment, svn copes slightly better than git. First project we tried it on had the worst possible environment, a mix of Windows and Linux systems. Line ending nightmares everywhere.
It also took a while to work out how to kill (with fast-forward) the spurious "merge commit" you get every time someone does a pull. You don't have that with svn, you just do the merging locally when you update and it doesn't generate a commit.
Edit: also in a Windows environment, svn copes slightly better than git. First project we tried it on had the worst possible environment, a mix of Windows and Linux systems. Line ending nightmares everywhere.
It also took a while to work out how to kill (with fast-forward) the spurious "merge commit" you get every time someone does a pull. You don't have that with svn, you just do the merging locally when you update and it doesn't generate a commit.
I've been using Subversion since 10 years or so and I've changed completely to Git, so I've got experience with it.
For me Git was really a much needed upgrade to subversion. Working with branches (testing and production, we even have some repositories with multiple testing and production branches) are working like they are supposed to do. Changing commits (oops - I forgot to add one file) before pushing them to the repository for the other users is another big advantage. Working on multiple features in parallel - I couldn't do that with Subversion.
We've nearly completely eliminated the "handcrafted" local copies with multiple half finished features since changing to Git.
And if you want to use Git as a Subversion alternative you can use it in this mode too - altough you are missing out on some good new features.
I don't want to change back to Subversion.
The only disadvantage is that SourceTree (the GUI tool we are using) is a pretty lame duck in Windows. But the command line is excellent.
For me Git was really a much needed upgrade to subversion. Working with branches (testing and production, we even have some repositories with multiple testing and production branches) are working like they are supposed to do. Changing commits (oops - I forgot to add one file) before pushing them to the repository for the other users is another big advantage. Working on multiple features in parallel - I couldn't do that with Subversion.
We've nearly completely eliminated the "handcrafted" local copies with multiple half finished features since changing to Git.
And if you want to use Git as a Subversion alternative you can use it in this mode too - altough you are missing out on some good new features.
I don't want to change back to Subversion.
The only disadvantage is that SourceTree (the GUI tool we are using) is a pretty lame duck in Windows. But the command line is excellent.
So what problems exactly did you have with SVN?
branches are branches in svn or git... your process may not have been correct, but lets not blame the tools here..
modifying commits is a big no-no for me, so thats not a drawback at all, the fact that its not possible in svn is a win for svn.
branches are branches in svn or git... your process may not have been correct, but lets not blame the tools here..
modifying commits is a big no-no for me, so thats not a drawback at all, the fact that its not possible in svn is a win for svn.
I really like modifying commits (as long as they are not pushed) - but I know that this is quite a controversial topic.
For one of our biggest projects branches in SVN didn't work at all.
We have multiple production, test and development branches and merge branches (features) from one branch to the other (development -> testing -> production). Sometimes we cherry pick a single commit to another branch.
In those days SVN wasn't so flexibel with branches as we wanted to (or we didn't understand it enough), so our workflow was much more rigid.
For one of our biggest projects branches in SVN didn't work at all.
We have multiple production, test and development branches and merge branches (features) from one branch to the other (development -> testing -> production). Sometimes we cherry pick a single commit to another branch.
In those days SVN wasn't so flexibel with branches as we wanted to (or we didn't understand it enough), so our workflow was much more rigid.
I'll second brusch64 here.
I used SVN for 7 or 8 years and then Git for the past 3, with about a year of overlap (on different repos).
To me, Git is vastly superior. I tend to use it in quite an "SVN-like" fashion - there's a single main trunk branch that we all share - but in terms of what I can do locally it blows SVN out of the water.
The difference is that Git makes things that are hard or impossible in SVN trivial. So for e.g. I create local branches all the time; I commit a bunch of small changes locally as I experiment with a fix, and then `merge --squash` to leave a clean history for others; merging fixes across different branches is easy and just works.
I used SVN for 7 or 8 years and then Git for the past 3, with about a year of overlap (on different repos).
To me, Git is vastly superior. I tend to use it in quite an "SVN-like" fashion - there's a single main trunk branch that we all share - but in terms of what I can do locally it blows SVN out of the water.
The difference is that Git makes things that are hard or impossible in SVN trivial. So for e.g. I create local branches all the time; I commit a bunch of small changes locally as I experiment with a fix, and then `merge --squash` to leave a clean history for others; merging fixes across different branches is easy and just works.
Finally someone with a real advantage that a DVCS (not necessarily git) has over SVN.... local branches.
Most people just spout the same sheep-like line "git>svn" without being able to justify it!
Most people just spout the same sheep-like line "git>svn" without being able to justify it!
I concur. I would assume that git is the right tool for Linus's workflow, but whatever that is, it isn't mine. SVN does all I need and it has a friendly API and helpful documentation. In other words, the exact opposite of git.
[deleted]
SVN is a glorified backup - which is basically what you're saying.
The SVN UI is just horrid in other dimensions, mainly the "you can't do that at all" one.
The SVN UI is just horrid in other dimensions, mainly the "you can't do that at all" one.
sorry... you come across as a git-sheep.
(getting down-voted for it, but someone has to say it)
(getting down-voted for it, but someone has to say it)
I'm prepared to give you a lot of examples (which other people might value differently). From the unfortunate consequences of the 'branches are files (and therefore tags are easily mutable by default and surprisingly hard to pin down)' to usual "I just committed, why does 'svn log' not show that?", to git bisect, to git clean and the stubbornness with which svn refuses to even consider implementing that.
TortoiseSVN provides the "clean" functionality if you want it.
that sounds like process-issues... not SVN issues.
tags should not be committed to... end-of-story.
as for 'svn-log not showing commits'... I've never heard of that one in the last decade of using it... I'm genuinely interested in how that came about.
tags should not be committed to... end-of-story.
as for 'svn-log not showing commits'... I've never heard of that one in the last decade of using it... I'm genuinely interested in how that came about.
What are the superior foes in your opinion ?
I don't know any of the other distributed version control systems. The only other version control system I have much (too much) experience with is Subversion and it can't hold a candle against Git.
In my opinion Git is the C language of version control systems. If you are careless it's not the tool for you. Otherwise you have a really great tool with lots of power.
I don't know any of the other distributed version control systems. The only other version control system I have much (too much) experience with is Subversion and it can't hold a candle against Git.
In my opinion Git is the C language of version control systems. If you are careless it's not the tool for you. Otherwise you have a really great tool with lots of power.
I don't know any of the other distributed version control systems.
In an ideal world -- one where network effects of GitHub hadn't crushed all competition -- I'd get to choose Mercurial as my daily version-control system. It has similarities to git, in that both are largely user interfaces to a DAG, but its guiding philosophy and approach to the interface it exposes are far better in my opinion.
In my opinion Git is the C language of version control systems. If you are careless it's not the tool for you.
You probably don't want to make that assertion; we now have close to half a century of evidence that no human currently living can use C safely, and I don't think you'd want that to carry over to git. And it's not a matter of "careless" or not -- extremely intelligent, extremely-well-trained, extremely-careful people still write unsafe C.
In an ideal world -- one where network effects of GitHub hadn't crushed all competition -- I'd get to choose Mercurial as my daily version-control system. It has similarities to git, in that both are largely user interfaces to a DAG, but its guiding philosophy and approach to the interface it exposes are far better in my opinion.
In my opinion Git is the C language of version control systems. If you are careless it's not the tool for you.
You probably don't want to make that assertion; we now have close to half a century of evidence that no human currently living can use C safely, and I don't think you'd want that to carry over to git. And it's not a matter of "careless" or not -- extremely intelligent, extremely-well-trained, extremely-careful people still write unsafe C.
>we now have close to half a century of evidence that no human currently living can use C safely
How many operating systems are written in C ?
How many of the more mainstream operating systems are written in other languages ?
You're right that C is the wrong tool for a lot of applications. But if you need total control and speed and power it still works for many projects.
You're right that C is the wrong tool for a lot of applications. But if you need total control and speed and power it still works for many projects.
I've heard a lot of people who seem to know their stuff say that Mercurial is superior to Git in almost every way, especially when it comes to integrating with other tooling (i.e. Mercurial seems to have an API whereas automating Git boils down to spawning shell commands). This also seems to be why Facebook switched from Git to Mercurial: they needed to be able to check out individual folders from a branch and Git simply didn't provide any way to do that without first checking out the entire branch.
Be that as it may, it's a common misconception that the more popular tool is always the better tool. There are a lot of factors to a tool's success and the technical ones are generally far less important than most people think.
Be that as it may, it's a common misconception that the more popular tool is always the better tool. There are a lot of factors to a tool's success and the technical ones are generally far less important than most people think.
What's so bad about spawning shell commands?
People have already mentioned it, but since I made the original comment, I'll pile on and say that Mercurial was (well, still is, but it's out of fashion now) awesome. It matches Git on most axes and blows it out of the water when it comes to usability and "don't shoot yourself in the foot"-ishness.
Brushing aside some relatively minor differences, Mercurial is very similar to Git, except that it was designed by people that don't have an all-consuming disdain for all of humankind.
Brushing aside some relatively minor differences, Mercurial is very similar to Git, except that it was designed by people that don't have an all-consuming disdain for all of humankind.
Can you justify git>subversion or are you just following the sheep?
Not saying I disagree... but subversion is still king in the corporate-engineering companies and it tends to work well in those types of setups.
Just beware of having unjustified-opinions. SVN may not be trendy... but neither will git in a few years time.
BTW: Mercurial still beats them all.
Not saying I disagree... but subversion is still king in the corporate-engineering companies and it tends to work well in those types of setups.
Just beware of having unjustified-opinions. SVN may not be trendy... but neither will git in a few years time.
BTW: Mercurial still beats them all.
>subversion is still king in the corporate-engineering companies and it tends to work well in those types of setups.
For some values of "work". We're using SVN at my new job, with a single trunk branch. Not having the ability to commit locally, and mess around with local branches is a pain in the ass. I found a solution though. I cloned SVN repo using git-svn and now I can make local commits like a pro, and use my beloved magit (Emacs git interface).
For some values of "work". We're using SVN at my new job, with a single trunk branch. Not having the ability to commit locally, and mess around with local branches is a pain in the ass. I found a solution though. I cloned SVN repo using git-svn and now I can make local commits like a pro, and use my beloved magit (Emacs git interface).
Yes, git-svn is probably the reason why the mutiny didn't happen yet in some departments. You can identify their users by having several SVN commits in as many seconds.
(I used git in an cvs-to-svn migration, and stayed since.)
(I used git in an cvs-to-svn migration, and stayed since.)
for me the biggest advantage is working in my own repository and then pushing the changes upstream. I can develop features independent of other features. If there is a bug I can fix it, merge it into the productive branch and carry on working on other features.
I know that many people don't like it, but I can fix up commits in my local repository and push the change upstream in one.
With SVN I wasn't able to do this, so it was a big pain if you had to fix a bug if you were in the middle of a big feature, or if you had an experimental feature you wanted to clean up and release a month later.
I know that many people don't like it, but I can fix up commits in my local repository and push the change upstream in one.
With SVN I wasn't able to do this, so it was a big pain if you had to fix a bug if you were in the middle of a big feature, or if you had an experimental feature you wanted to clean up and release a month later.
> just happened to win the PR battle against its superior foes, because...Idunno, Linux, I guess?
I would assume GitHub is to blame for that> terrible software
The Git DAG and its content-addressable file system are an elegant solution to the problem of distributed version control. The implementation is clean and dead-simple, yet immensely powerful. This is the basis of good engineering.
> an even worse UX
Git was designed to expose its underlying implementation and not to isolate the user from it. Unlike other systems, its subcommands give the user the ability to manipulate the underlying data structure directly.
That doesn't mean it has a bad UX. Just that it has the UX of a power tool.
I also think that Git played a big role in the growth and popularity of command-line tools over the past decade. And that its interface inspired the subcommand pattern that is now commonplace in docker, vagrant, and others.
The Git DAG and its content-addressable file system are an elegant solution to the problem of distributed version control. The implementation is clean and dead-simple, yet immensely powerful. This is the basis of good engineering.
> an even worse UX
Git was designed to expose its underlying implementation and not to isolate the user from it. Unlike other systems, its subcommands give the user the ability to manipulate the underlying data structure directly.
That doesn't mean it has a bad UX. Just that it has the UX of a power tool.
I also think that Git played a big role in the growth and popularity of command-line tools over the past decade. And that its interface inspired the subcommand pattern that is now commonplace in docker, vagrant, and others.
First time I've wanted to upvote twice!
I think besides a PR battle (there's PR people for RCS'es??) I think Git won out because "the server was free". Competitors at the time needed a big (if there were large numbers of committers) server that someone had to pay for. By that I mean the hardware to host the server -- Git needs either none, or a very lightweight machine for a server.
I think besides a PR battle (there's PR people for RCS'es??) I think Git won out because "the server was free". Competitors at the time needed a big (if there were large numbers of committers) server that someone had to pay for. By that I mean the hardware to host the server -- Git needs either none, or a very lightweight machine for a server.
> ... that just happened to win the PR battle ...
Chalk that up to the power of fashion. Otherwise, people would use an SCM that doesn't destroy their work in the blink of an eye and actually has an API that deserves the name.
Chalk that up to the power of fashion. Otherwise, people would use an SCM that doesn't destroy their work in the blink of an eye and actually has an API that deserves the name.
>I don't know if this post was intended as humour or a way to vent out some frustration but in my experience, this path of treating git as "spell X solves problem Y" will always break dow
I disagree. "spell X solves problem Y" is an excellent way to both get started with fixing your Y fast AND for learning a system deeper.
I think we better learn by example (such as that) and in practical use over time, as opposed to getting some abstract knowledge of the whole system first, or (god forbid) reading the manual, which noone does.
I disagree. "spell X solves problem Y" is an excellent way to both get started with fixing your Y fast AND for learning a system deeper.
I think we better learn by example (such as that) and in practical use over time, as opposed to getting some abstract knowledge of the whole system first, or (god forbid) reading the manual, which noone does.
I disagree. Using Git (or any terminal interaction for that matter) is much like speaking a language. As a metaphor: you might be able to order two beers in German (zwei Bier bitte), but the moment the waitress asks you what brand you want it comes down to guessing.
Some coworkers (across all experience levels) use Git this way. It's frustrating how slowly they learn and conversely, how inefficiently they work.
Some coworkers (across all experience levels) use Git this way. It's frustrating how slowly they learn and conversely, how inefficiently they work.
>Using Git (or any terminal interaction for that matter) is much like speaking a language
Which again, we learn best by absorbing bits and pieces piecemeal over time -- that's how toddlers learn their native language, by immersion. Not by getting some "understanding of fundamentals" course first.
Which again, we learn best by absorbing bits and pieces piecemeal over time -- that's how toddlers learn their native language, by immersion. Not by getting some "understanding of fundamentals" course first.
Knowing Git "inside out" is great, but you can't expect to know/remember every command for every situation from day one or even day one thousand. A list of ways to solve Git problems serves as a refresher and even a tool for gaining more insight into how it works as a whole.
I think there's a bit of that in git in particular.
The irony is that if you think of git in terms of deltas, with branches just being tags to commits, and "git commit" actually being "git commit + move branch", then a lot of stuff is easier to reason about.
Like, if you get the notion of working tree, staging area, commits, and branches on a deep-ish level, things get easier. Things can still be hard, but there's a lot less "does running this cause everything to disappear???"
I think it would be possible to make this awesome page even more awesome with a little "annotated version" that gives the details of what you're actually doing.
The irony is that if you think of git in terms of deltas, with branches just being tags to commits, and "git commit" actually being "git commit + move branch", then a lot of stuff is easier to reason about.
Like, if you get the notion of working tree, staging area, commits, and branches on a deep-ish level, things get easier. Things can still be hard, but there's a lot less "does running this cause everything to disappear???"
I think it would be possible to make this awesome page even more awesome with a little "annotated version" that gives the details of what you're actually doing.
> and "git commit" actually being "git commit + move branch"
Can you elaborate on that a little more? I liked where it was going -- because being able to explain how git works to someone coming from SVN has been an ongoing problem for me.
Can you elaborate on that a little more? I liked where it was going -- because being able to explain how git works to someone coming from SVN has been an ongoing problem for me.
In git, branches are pointers to commits (branches are a specific kind of refs or references). When you commit, git creates a new commit object, links it to the last commit on
that branch, and then points that branch to the new commit.
This way, you get a chain of commits, each pointing to the previous commit, and and branch references pointing to the last commit of each branch.
This way, you get a chain of commits, each pointing to the previous commit, and and branch references pointing to the last commit of each branch.
Simplifying things a bit, git is what you did before you learned about using version control. That's right, it's just the old copy/paste the entire project folder for each revision and give it a name like "Project v1", "Project v2", etc. Branches and tags are then just symlinks to a specific folder.
In this world, when you commit, you're doing two things: 1. Creating a new top level folder, e.g. "Project v42". 2. Updating the branch symlink you are on to point to that new folder.
I'm actually not simplifying things that much here, the main git addition is that each folder (revision) also has a list of previous folders (revisions) and that the folders (revisions) are not named sequentially, they are named based on a hash of their contents.
In this world, when you commit, you're doing two things: 1. Creating a new top level folder, e.g. "Project v42". 2. Updating the branch symlink you are on to point to that new folder.
I'm actually not simplifying things that much here, the main git addition is that each folder (revision) also has a list of previous folders (revisions) and that the folders (revisions) are not named sequentially, they are named based on a hash of their contents.
I agree that it's worth it learning git properly, but sometimes you're thrown into the deep end and don't have the time to get up to speed the "right way". I think git is complicated enough to warrant some simplified descriptions for the most-required tasks.
> sometimes you're thrown into the deep end and don't have the time to get up to speed the "right way".
So you don't have three hours to read the fsckin' manual that describes how git repository is organized? O_o
So you don't have three hours to read the fsckin' manual that describes how git repository is organized? O_o
At this point I think we need to define what it means to "learn git properly". The assumption in this discussion is that it is more than learn a few concrete commands for specific tasks in a few minutes. You say 3 hours is sufficient, but is it?
For example, something as simple as "Changing the Last Commit" (as in "git commit --amend") is found in chapter 7.6 in the git book which is given as main documentation on git-scm.org. The first 6 chapter mainly deal with introducing the model, architecture and high level workflows. Even if you skip the chapter on github, that's still 5 chapters on mostly theory to read before you get to some often-used tool commands. I would argue that is more than 3 hours for most people if you don't just skim it but try to also understand it.
Apart from that, to answer the question: indeed, often I don't have 3 hours for something to be considered "nice to know" as opposed to "absolutely necessary". And if the manual is a "fsckin'" one, I'm unlikely to read it at all.
For example, something as simple as "Changing the Last Commit" (as in "git commit --amend") is found in chapter 7.6 in the git book which is given as main documentation on git-scm.org. The first 6 chapter mainly deal with introducing the model, architecture and high level workflows. Even if you skip the chapter on github, that's still 5 chapters on mostly theory to read before you get to some often-used tool commands. I would argue that is more than 3 hours for most people if you don't just skim it but try to also understand it.
Apart from that, to answer the question: indeed, often I don't have 3 hours for something to be considered "nice to know" as opposed to "absolutely necessary". And if the manual is a "fsckin'" one, I'm unlikely to read it at all.
Git has enough bells and whistles that a cheat sheet is fine, in my opinion. It's only a problem if you don't understand the commands (the same problem as blind copy-pasting code from the web)
> this path of treating git as "spell X solves problem Y" will always break down
I agree completely! Anytime you give a list of 'run this command', I think you've actually written a CLI tool in the wrong language (English instead of a programming language).
At work, we want to increase dev's confidence with git in the next few months. We're making sure to separate out 'Technical' knowledge (what do steps do I perform to recover a deleted branch) from 'Conceptual' knowledge (why would it be a good/bad idea to delete a branch, how branches are intended to be used, understanding what git thinks a branch is, etc.). The former go into git aliases or CLI swiss army knife tool, the latter into training videos and workshops.
I agree completely! Anytime you give a list of 'run this command', I think you've actually written a CLI tool in the wrong language (English instead of a programming language).
At work, we want to increase dev's confidence with git in the next few months. We're making sure to separate out 'Technical' knowledge (what do steps do I perform to recover a deleted branch) from 'Conceptual' knowledge (why would it be a good/bad idea to delete a branch, how branches are intended to be used, understanding what git thinks a branch is, etc.). The former go into git aliases or CLI swiss army knife tool, the latter into training videos and workshops.
it was really hard for me to understand vim until a website explained it as being a set of grammars you can learn.
i agree, if you really want to be more productive (and without having to go find some git expert on your team) knowing how each operation works and why its doing what its doing is really beneficial.
despite that, its sometimes frustrating due to inconsistencies in the git "grammar" that i sometimes don't understand, like why if you want to apply only one file from git stash you have to use `git checkout` rather than `git stash apply [<stash>] -- <file>`. it makes "sense" but is unintuitive when i'm thinking about using stashed commits.
i agree, if you really want to be more productive (and without having to go find some git expert on your team) knowing how each operation works and why its doing what its doing is really beneficial.
despite that, its sometimes frustrating due to inconsistencies in the git "grammar" that i sometimes don't understand, like why if you want to apply only one file from git stash you have to use `git checkout` rather than `git stash apply [<stash>] -- <file>`. it makes "sense" but is unintuitive when i'm thinking about using stashed commits.
The absolutely easiest way to learn vim is to just schedule a reminder every ... month? week? to run "vimtutor". Then do that for a few minutes until you get frustrated or want to do something else. It's shocking how fast you'll learn.
[deleted]
Thank you for this! I didn't know `vimtutor` existed, and just finished the first full lesson. I've got to work now, but I'll be back.
Thank you!
Thank you!
I think the reason you're disagreeing is that you're not looking at this from a beginner's point of view.
Generally there are (roughly) three approaches depending on where you are in your journey from beginner to expert:
As a beginner, you need specific, detailed, step-by-step instructions: First run X, then run Y, finally run Z, if something goes wrong along the way, follow these other steps, if that doesn't work, ask someone for help.
Once you've moved beyond being a beginner, you understand how the different steps are connected, so you already know the intermediate steps and just need to be told the task at hand: do an X (e.g. "move these commits onto the other branch").
An expert fully understands all the inner workings and just needs to be told the big picture: this is what I have, that is what I want, make it happen.
If you try to instruct experts like beginners, they will be frustrated because it seems so tedious and you're not giving them the information they want: what you're trying to do. If you try to instruct beginners like experts, they will be horribly confused because they don't know how to make any of it happen without you laying out each individual step they need to follow.
A case can be made that a beginner should learn each individual operation by heart before moving on to the next one (like kata in martial arts) but this style of learning assumes you're willing to spend a lifetime perfecting a single art. It's unlikely git will stick around that long and for most of its users git is just a tiny (though important) aspect of their work.
Generally there are (roughly) three approaches depending on where you are in your journey from beginner to expert:
As a beginner, you need specific, detailed, step-by-step instructions: First run X, then run Y, finally run Z, if something goes wrong along the way, follow these other steps, if that doesn't work, ask someone for help.
Once you've moved beyond being a beginner, you understand how the different steps are connected, so you already know the intermediate steps and just need to be told the task at hand: do an X (e.g. "move these commits onto the other branch").
An expert fully understands all the inner workings and just needs to be told the big picture: this is what I have, that is what I want, make it happen.
If you try to instruct experts like beginners, they will be frustrated because it seems so tedious and you're not giving them the information they want: what you're trying to do. If you try to instruct beginners like experts, they will be horribly confused because they don't know how to make any of it happen without you laying out each individual step they need to follow.
A case can be made that a beginner should learn each individual operation by heart before moving on to the next one (like kata in martial arts) but this style of learning assumes you're willing to spend a lifetime perfecting a single art. It's unlikely git will stick around that long and for most of its users git is just a tiny (though important) aspect of their work.
"A lifetime" is massively exaggerated. I would argue that I know the majority of intricacies of every git command, and I've spent much less than a lifetime on this (about 2 years in reality, alongside other things, of course).
> As a beginner, you need specific, detailed, step-by-step instructions: First run X, then run Y, finally run Z, if something goes wrong along the way, follow these other steps, if that doesn't work, ask someone for help.
That's one way to do it, but it's not preferable. I would rather sit the beginner down for at least an hour and go through the basic concepts with them.
I've taught Git to a few people (mostly fellow students or colleagues) and I found that they have a much easier time when they are introduced early on to the basic concepts of Git (the commit graph, and branches/tags as pointers into the graph), they have a much easier time grasping relevant tasks like merge and rebase.
For specific questions (mostly in these "I screw up" moments), a whiteboard is also really helpful to explain them how the two or three magic commands that I tell them are actually fixing things up.
> As a beginner, you need specific, detailed, step-by-step instructions: First run X, then run Y, finally run Z, if something goes wrong along the way, follow these other steps, if that doesn't work, ask someone for help.
That's one way to do it, but it's not preferable. I would rather sit the beginner down for at least an hour and go through the basic concepts with them.
I've taught Git to a few people (mostly fellow students or colleagues) and I found that they have a much easier time when they are introduced early on to the basic concepts of Git (the commit graph, and branches/tags as pointers into the graph), they have a much easier time grasping relevant tasks like merge and rebase.
For specific questions (mostly in these "I screw up" moments), a whiteboard is also really helpful to explain them how the two or three magic commands that I tell them are actually fixing things up.
One of my SO questions could almost fit in there, somewhere before "Fuck this noise...":
http://stackoverflow.com/questions/28759887/git-gc-no-space-...
http://stackoverflow.com/questions/28759887/git-gc-no-space-...
From the section on using `git commit --amend`:
> This usually happens to me if I merge to master, then run tests/linters.
If this happens on more than one occasion, I’d strongly consider creating a pre-commit hook to run tests and/or lint the changed files, e.g., I run `checkbashisms` and `shellcheck` as a pre-commit hook when working on shell scripts.
> This usually happens to me if I merge to master, then run tests/linters.
If this happens on more than one occasion, I’d strongly consider creating a pre-commit hook to run tests and/or lint the changed files, e.g., I run `checkbashisms` and `shellcheck` as a pre-commit hook when working on shell scripts.
I constantly wonder if there's a "better CLI UI" that can be made for git, even if simply a wrapper around git.
Ie, if the implementation of Git is right, but only the cli commands/etc are wrong.. what would the right UX be? What would a friendly UX look like?
Seems like something a lot of people could love - even if blasphemy to Git purists.
Ie, if the implementation of Git is right, but only the cli commands/etc are wrong.. what would the right UX be? What would a friendly UX look like?
Seems like something a lot of people could love - even if blasphemy to Git purists.
Great article. A couple notes
Just git reset <ref> should do. The --soft flag is implicit.
Amending and rebasing is something you should be careful with. If you've already pushed, you'll now need to force push. If another person has put new commits upstream, they will be wiped out irreparably. Not saying don't do it, just that it's very risky.
Instead of deleting and recloning the repo at the end, if you're really at that point, just doing git reset --hard origin/master should be equally as effective with fewer steps and less time.
Pulling down the repo a second time, however, can be more useful for just having a snapshot of the code in a second location that is totally independent of git traffic (don't pull to it very often). Say someone force pushes something that removes code. Your snapshot or someone else's non-pulled repo is your only hope of getting it back.
Just git reset <ref> should do. The --soft flag is implicit.
Amending and rebasing is something you should be careful with. If you've already pushed, you'll now need to force push. If another person has put new commits upstream, they will be wiped out irreparably. Not saying don't do it, just that it's very risky.
Instead of deleting and recloning the repo at the end, if you're really at that point, just doing git reset --hard origin/master should be equally as effective with fewer steps and less time.
Pulling down the repo a second time, however, can be more useful for just having a snapshot of the code in a second location that is totally independent of git traffic (don't pull to it very often). Say someone force pushes something that removes code. Your snapshot or someone else's non-pulled repo is your only hope of getting it back.
Just a tiny correction: git reset <ref> defaults to --mixed, not --soft. The only difference is whether or not files are staged. Since the OP used --soft, I believe the subsequent `git add .` is unnecessary since the files should already be staged when --soft is used.
Regarding the case of an erroneous force push removing code, usually things can be recovered by looking through the reflog and doing some surgery via the lower-level plumbing commands... it's not exactly a fun process though :)
Regarding the case of an erroneous force push removing code, usually things can be recovered by looking through the reflog and doing some surgery via the lower-level plumbing commands... it's not exactly a fun process though :)
I've heard advice from #git on freenode not to use "git commit --amend", especially on shared repos.
I wish I still had a log of the conversation or remembered the exact problem that led up to it, but it involved a simple amend totally screwing up my repo, and I've avoided it since.
I wish I still had a log of the conversation or remembered the exact problem that led up to it, but it involved a simple amend totally screwing up my repo, and I've avoided it since.
The problem occurs when you amend a commit that someone else is already using. That is rewriting the shared history. A merge commit is required to get the branches in sync again.
Amending your commit in your own feature branch or fork isn't a problem. I often amend commits to make a cleaner git history to ease PR/code review.
Amending your commit in your own feature branch or fork isn't a problem. I often amend commits to make a cleaner git history to ease PR/code review.
git checkout master
git checkout -b 10-new-feature
# Make changes
git add example.code
git commit
git push origin 10-new-feature
# Oops... left a debug message, fix it.
git add example.code
git commit --amend
git push -f # Rewrites the remote history with your local modified version
Consider --amend as the "Just the last commit" form of rebasing.I upvoted and am hopefully awaiting a response from someone who can chime in and explain why this is a problem.
Amend after push, I could see. You commit, push, amend, push, but after your first push someone else pushes... then you have two heads. I could see that, but I'm guessing you'd mention that if it were the case.
If one were to attempt avoiding amend you could always make all changes in a feature branch and rebase this branch onto your target afterwards, squashing commits.
Amend after push, I could see. You commit, push, amend, push, but after your first push someone else pushes... then you have two heads. I could see that, but I'm guessing you'd mention that if it were the case.
If one were to attempt avoiding amend you could always make all changes in a feature branch and rebase this branch onto your target afterwards, squashing commits.
It's much like rebasing, with a similar set of benefits and drawbacks.
Once other people can be expected to have done work based on your amended or rebased work, you can expect some annoyances (or worse). If you haven't pushed yet (or if you're really, really sure nobody's basing further work on something you've recently pushed), I say go crazy and amend and rebase to your heart's content.
Once other people can be expected to have done work based on your amended or rebased work, you can expect some annoyances (or worse). If you haven't pushed yet (or if you're really, really sure nobody's basing further work on something you've recently pushed), I say go crazy and amend and rebase to your heart's content.
I've been debating starting a section of my personal site for stuff like this. Unfortunately it's a bit embarrassing, but i figure anything i have to google to learn, it would be beneficial to help others learn it as well. Everything from programming languages (lots of Rust errors are foreign to me, for example), to git issues.
I've often had the thought that if everyone did this it could have potential to be quite the open-sourced collection of material - a distributed self-answered Stack Overflow perhaps.
Is there any sanity in this? Or would posting everything as self-answers to Stackoverflow be more welcome to the average Googler? (higher ranking, better meta, more likely for the user to see it and community features such as commenting/voting/editing)
I've often had the thought that if everyone did this it could have potential to be quite the open-sourced collection of material - a distributed self-answered Stack Overflow perhaps.
Is there any sanity in this? Or would posting everything as self-answers to Stackoverflow be more welcome to the average Googler? (higher ranking, better meta, more likely for the user to see it and community features such as commenting/voting/editing)
Please file bugs for bad errors in Rust. We have an entire tag dedicated to them, and have been doing a lot of work to make them better. A non-understandable error is a bug.
I just uploaded a presentation I gave last February called "Git back on your feet":
http://www.slideshare.net/ChristianCouder/git-back-onyourfee...
http://www.slideshare.net/ChristianCouder/git-back-onyourfee...
Great idea! We need more basic git workflows described in plain English.
I was expecting some actual "bad" situations based on the title, and to be fair these were bad to me once and are bad for people new to git, but I'd love to see the level 2,3,etc. version of this article.
I was expecting some actual "bad" situations based on the title, and to be fair these were bad to me once and are bad for people new to git, but I'd love to see the level 2,3,etc. version of this article.
Here's my standard recommendations:
* Learn Git Branching (gentle introduction to git's UI, with a visualization of the DAG) [0]
* Git for ages 4 and up (beginner-oriented, teaches you how to model git's internal concepts, 90m video) [1]
* Git from the bottom-up (high-level overview of git's internal data structures) [2]
* My Git Habits (sophisticated, you will have to study the man pages used to completely internalize the workflow) [3]
[0]: http://pcottle.github.io/learnGitBranching/
[1]: https://youtu.be/1ffBJ4sVUb4
[2]: http://ftp.newartisans.com/pub/git.from.bottom.up.pdf
[3]: http://blog.plover.com/prog/git-habits.html
* Learn Git Branching (gentle introduction to git's UI, with a visualization of the DAG) [0]
* Git for ages 4 and up (beginner-oriented, teaches you how to model git's internal concepts, 90m video) [1]
* Git from the bottom-up (high-level overview of git's internal data structures) [2]
* My Git Habits (sophisticated, you will have to study the man pages used to completely internalize the workflow) [3]
[0]: http://pcottle.github.io/learnGitBranching/
[1]: https://youtu.be/1ffBJ4sVUb4
[2]: http://ftp.newartisans.com/pub/git.from.bottom.up.pdf
[3]: http://blog.plover.com/prog/git-habits.html
You know, a few years back I had exactly the same attitude towards Git. I hated it, tried to approach multiple times and still hated it. But after working with Git on multiple projects, and having developed some deeper understanding of how things work there, I honestly think now that Git is one of the best tools that have been invented over last 20 years for improving the development processes and engineering excellence. I don't really want to defend it, the learning curve is apparently pretty steep (at least it was for me), but I would just recommend to not give up and keep trying. There are some good tutorials how to handle it and why it's helpful (Atlassian's Git book, for instance).
Oh shit, I commited a binary file larger than 100 mb and now i can't push to github.com. Solution: https://rtyley.github.io/bfg-repo-cleaner/
Is there some tool that runs a full internal consistency check on a git repo?
Because otherwise, how can I be sure that some tool didn't mess up my repo, and one day I'll be getting error messages when checking out files, etcetera?
Because otherwise, how can I be sure that some tool didn't mess up my repo, and one day I'll be getting error messages when checking out files, etcetera?
git fsck
This. Also, hold on to the commit before you started refactoring (preferably by placing a temporary branch there, in order to avoid premature garbage collection). Then after your refactoring is done, `git fsck` and `git diff --stat $old_branch..HEAD` to verify that you did not lose any important content during the refactoring.
That is true in general. However, in the context of bfg-repo-cleaner, that doesn't help, because the purpose of the bfg-repo-cleaner is to completely remove commits that match the criteria you give it. I say this not to "correct" you per se, because you are correct, but to ensure that people using bfg-repo-cleaner do not believe that this will help them.
The "correct" course of action prior to using the bfg-repo-cleaner is to make a complete copy of the target .git directory. I've used it many times and it seems quite reliable, but if nothing else, that's a good defense against terminating it halfway through accidentally or something. (Of course even without that, you shouldn't be operating on the only copy of your .git repo anyhow since it is almost certainly somewhere else, too, or you wouldn't be having the problem bfg-repo-cleaner is designed to solve in the first place. But losing your own local branches and work is still a pain.)
The "correct" course of action prior to using the bfg-repo-cleaner is to make a complete copy of the target .git directory. I've used it many times and it seems quite reliable, but if nothing else, that's a good defense against terminating it halfway through accidentally or something. (Of course even without that, you shouldn't be operating on the only copy of your .git repo anyhow since it is almost certainly somewhere else, too, or you wouldn't be having the problem bfg-repo-cleaner is designed to solve in the first place. But losing your own local branches and work is still a pain.)
git add .
Ugh, no, never do this, never recommend to users to BLINDLY ADD ALL THE CHANGES FROM THE WORKING COPY. I honestly can't think of any worse git usage than this.Add the single change you missed, or even better, `git add -p`, to add chunks manually.
The screwed up and committed to master should end with:
git reset --hard origin/master
(assuming that the remote is called "origin") With the example in the text, you have to know the number of commits you've made to master.It was also a bit pointless to checkout a new branch just to switch back. The whole thing should be
git branch some-new-branch-name
git reset --hard origin/master
git checkout some-new-branch-nameThe "committed to wrong branch" case is also a little overly complex. I'd just do:
git checkout correct-branch
git cherry-pick wrong-branch
git checkout wrong-branch
git reset --hard HEAD~This is less safe than the branching alternatives. Instead of "moving" the original commit, this copies the original commit to a new one and leaves the original one dangling and waiting to be garbage collected.
Also, if you have more than one commit before you noticed you were on the wrong branch, this only grabs the one commit.
Also, if you have more than one commit before you noticed you were on the wrong branch, this only grabs the one commit.
tip: you can use @{u} to refer to "the upstream of my current branch", ie. what you said but will work no matter what the remote is called.
the website's example is for when you only want to undo just the last commit you made.
> Bizarrely, git won't do a dif of files that have been add-ed to your staging area without this flag
Not sure what's bizarre about that. Doing so helps keep your commits clean and helps git tools (diff, git-gutter, etc) by ignoring things you've already stated are complete.
For example, I quickly fix a bug. The code is ugly and I don't want to commit it yet. So I add the bugfix files. Then I clean up the code (before commiting). Now I can do another diff between the staged and unstaged files, checking that it looks better than before, and still works. This way there is 1 clean commit "bugix" and not 2 commits "bugfix" and "bugfix code cleanup"
Not sure what's bizarre about that. Doing so helps keep your commits clean and helps git tools (diff, git-gutter, etc) by ignoring things you've already stated are complete.
For example, I quickly fix a bug. The code is ugly and I don't want to commit it yet. So I add the bugfix files. Then I clean up the code (before commiting). Now I can do another diff between the staged and unstaged files, checking that it looks better than before, and still works. This way there is 1 clean commit "bugix" and not 2 commits "bugfix" and "bugfix code cleanup"
I managed to "rm -rf .git" at one point. Took me about a minute to realize and -surprisingly after <c-c>-ing i lost nothing (as far as i was aware). Git is freaking hard to break. Also always remember git-reflog, it safes lives.
Also great for getting out of Git messes: http://justinhileman.info/article/git-pretty/
I prefer stackoverflow for things like this as I can see from comments and up votes whether the command does what the poster claims, or whether it is going to make things worse for me.
Spend a few hours and really learn how Git works! Then you'll understand what those commands actually do and be able to judge for yourself. Great resources are the ProGit book, gittutorial(7) and eventually gitcore-tutorial(7) when you want to go deeper.
Nobody likes to read manuals or books, due to which one can see FAQs being posted on Q&A sites.
http://gitready.com/ contains a number of small articles categorized by beginner, intermediate and advanced that might be helpful.
Another resource for commonly used git tips and tricks: https://github.com/git-tips/tips
http://gitready.com/ contains a number of small articles categorized by beginner, intermediate and advanced that might be helpful.
Another resource for commonly used git tips and tricks: https://github.com/git-tips/tips
I moved to git at the begining of this year and I must say that I miss SVN. But everyone keeps telling me that git is better so I'm sticking to it.
Well, there are many more situations you can get into.
Like cherry picking, force pushing, merge --no-commit, rebasing... almost any operation can end up going wrong.
Just pay attention.
Like cherry picking, force pushing, merge --no-commit, rebasing... almost any operation can end up going wrong.
Just pay attention.
But he has the final solution to any git problem:
cd ..
sudo rm -r fucking-git-repo-dir
git clone https://some.github.url/fucking-git-repo-dir.gitHe needs to create a hook that deletes the repo the next time they do anything with the repo.
# create a new branch from the current state of master
git checkout -b some-new-branch-name
# remove the commit from the master branch
git checkout master
Or just `git branch some-new-branch-name`... cd ..
sudo rmdir nsfw-git-repo-dir
That will only remove it if it's empty? Which it never will be, because there's at least `.git/*`...Still, amusing :)
Fucking love it.
alias gitshit="open http://ohshitgit.com/"
alias gitshit="open http://ohshitgit.com/"
It's probably a good time to check if you have some safety against `rm -fr `.
Two days ago, I wanted to delete .git only, but accidentally as my fingers were accustomed with -fr , the command was `rm -fr * .git`. Rails server was running and some hope arose at the moment to just `lsof | grep` .. unfortunately that didn't work with me !
Ironically, all dot files have stuck as obvious :)
Two days ago, I wanted to delete .git only, but accidentally as my fingers were accustomed with -fr , the command was `rm -fr * .git`. Rails server was running and some hope arose at the moment to just `lsof | grep` .. unfortunately that didn't work with me !
Ironically, all dot files have stuck as obvious :)
> Ironically, all dot files have stuck as obvious :)
Those wouldn't have if you had set the following:
Those wouldn't have if you had set the following:
shopt -s dotglobgit to me is a work of art. There is a lot of complexity underneath but the end user sees something that is simple, fast and easy to use. It scales depending on user needs and It's easy to reason about.
This is a feat of engineering, to take something complex and make it easy for anyone to undestand and use. It shows real expertise and deep understanding of the area.
In many ways it's a shining example against the 'culture of complexity' that we increasingly find ourselves in. Here rather than simplying the objective is to be to make thing as complex as possible, usually in pursuit of extremely niche use cases or because either the expertise or the interest to simplify is not there. If git was designed in this culture it would be fragile, full of buzz words, poorly documented and prone to failure, and something only a few self appointed experts could reason about and use properly.
This is a feat of engineering, to take something complex and make it easy for anyone to undestand and use. It shows real expertise and deep understanding of the area.
In many ways it's a shining example against the 'culture of complexity' that we increasingly find ourselves in. Here rather than simplying the objective is to be to make thing as complex as possible, usually in pursuit of extremely niche use cases or because either the expertise or the interest to simplify is not there. If git was designed in this culture it would be fragile, full of buzz words, poorly documented and prone to failure, and something only a few self appointed experts could reason about and use properly.
> This usually happens to me if I merge to master, then run tests/linters... and FML, I didn't put a space after the equals sign.
Am I the only one that runs my tests before committing, let alone merging to master?
Am I the only one that runs my tests before committing, let alone merging to master?
Yeah, pushing untested code to master is not such a great way to work. Push to a remote branch other than master, test it there, then merge it into master.
That's pretty much git 101
That's pretty much git 101
That's pretty much software development 101. Been happening for decades before git.
Or test locally? I work in government contracting so everything is .Net and TFS, but even in this environment it's trivial to make sure your code isn't objectively broken:
1. Click "Run all tests"
On your local machine even thousands of tests only takes a few seconds including the build process. We've got automated testing in the dev and test environments as well but if you're failing those there's a failure in workflow somewhere. There's very little reason to fail a test or to have a broken build in source control.> Oh shit, I committed and immediately realized I need to make one small change!
If you don't want to change the commit message, in addition to --amend:
If you don't want to change the commit message, in addition to --amend:
git commit --amend --no-editThe post is missing the most important command : git --help
It would be nice to add these two:
Oh shit, someone checked-in huge file that shouldn't be in repo.
Oh shit, this folder I had been working on should have been in its own repo.
Oh shit, someone checked-in huge file that shouldn't be in repo.
Oh shit, this folder I had been working on should have been in its own repo.
for the rest of it there is http://git.io/git-tips
The last rmdir example should be rm -rf.
Maybe he has an alias named "rmdir" that executes "rm -rf"
I fear Git so much that I make zip packages of the repo before potentially destroying operations.
One of my favorite teachers in school was a dude-bro programmer who pretty sure as younger than me. He'd spent a summer at Google and made us use git and gerrit. I'm honestly a much better programmer thanks to him. I'm still using the git cli to this day.
I also still say "new up" an object thanks to him. I'm not so proud of that one.
I also still say "new up" an object thanks to him. I'm not so proud of that one.
Most of the time, stay calm. Do not `git push` hastily, and check `git status` if you can :)
Surprised he finds git to be complicated. It probably is deep down, but for day-to-day use, compare it to SVN.
Until I switched, there was always a panic when branching or merging. With git, I can branch like a nutter and things seem to still work out in the end.
Not sure why, perhaps someone else has a perspective on it.
Until I switched, there was always a panic when branching or merging. With git, I can branch like a nutter and things seem to still work out in the end.
Not sure why, perhaps someone else has a perspective on it.
In my experience it's all fine and dandy until you hit a rebase or merge that needs manual attention.
In mine, not quite. All forms of merges are simple: resolve, add, commit. Inside a rebase I find it harder to memorize whether I need to to the add and/or commit or rebase --continue does it for me.
And conflicts from 'stash pop' are somewhat counterintuitive to handle.
And conflicts from 'stash pop' are somewhat counterintuitive to handle.
All of those things and more are way easier to do with gitk and git gui.
If the owner is here: with javascript disabled the code is unreadable.
I'm curious, what would you say the % of sites you visit is where they're still useful without JS?
That question is not very useful the way it's written down. Some sites legimitately require JS (everything in the "web apps" territory; just try to imagine Grafana without JS), so I would ignore these (which I hope is in line with your intentions).
Of the sites that are mostly static content, I would estimate around 60%. There's a small chunk of sites that are just blank with JS disabled, and there's a larger chunk that will load images only when JS is enabled.
Of the sites that are mostly static content, I would estimate around 60%. There's a small chunk of sites that are just blank with JS disabled, and there's a larger chunk that will load images only when JS is enabled.
Yeah that was a poorly worded question, sorry. I'm interested in how far one can get without JavaScript on today's Internet. But it sounds like you don't disable it fully, just only on untrusted sites?
60% is better than I'd expect for sites you expect to work without JS. =)
60% is better than I'd expect for sites you expect to work without JS. =)
I use uMatrix and enable first-party JS by default. That allows me to get by on most sites. Sometimes I have to enable additional domains, mostly:
- ajax.googleapis.com and the like
- somethingsomething.cloudfront.com
- variations of the same domain (for example, hn.algolia.com queries algolia.net and algolianet.com)
By the way, it's a very valid question whether my model is actually more secure than just uBlock, but I like it on an emotional level because I feel in control.
- ajax.googleapis.com and the like
- somethingsomething.cloudfront.com
- variations of the same domain (for example, hn.algolia.com queries algolia.net and algolianet.com)
By the way, it's a very valid question whether my model is actually more secure than just uBlock, but I like it on an emotional level because I feel in control.
maybe also useful
https://gitlab.com/esr/reposurgeon
[deleted]
The last one is my usual tactic.
It is not the fault of Git if to use it you have to know it!
However would appreciate a quick and dirty handbook.
However would appreciate a quick and dirty handbook.
LOL. Bookmarking along with my other Git reference sites...
Not quite in the spirit of this article, but "I just want this /one/ file without the rest of the changes from branch foo" is something I use all the time
git checkout otherbranch
git checkout firstbranch -- fileIwant maybe1more
git commit -m "brought over files"Git is complex and nuanced, and short term purple think it's faster to memorize some commands instead of understanding the fundamentals.
I kept having problems with git, so I read a fucking book on it https://git-scm.com/book/en/v2
I'm not saying I never get into situations I can't get myself out of, but the examples in the oh shit website now look like obviously trivialities.
I kept having problems with git, so I read a fucking book on it https://git-scm.com/book/en/v2
I'm not saying I never get into situations I can't get myself out of, but the examples in the oh shit website now look like obviously trivialities.
It's easier to figure out the various workflows you need (most teams need very few - work on feature, sync code, commit/push/issue PR, release) and then scripting them.
I noticed that git errors on my team were almost eliminated when we started doing that - especially once I started adding sanity checks to the git workflows. It also allowed members of the team who previously struggled with git to contribute much more effectively - they'd be rebasing without even necessarily knowing what rebasing was, for instance.
It also meant that the git workflow, if it was version controlled, could also be amended.
This worked out much better than the git course people were sent on.
I noticed that git errors on my team were almost eliminated when we started doing that - especially once I started adding sanity checks to the git workflows. It also allowed members of the team who previously struggled with git to contribute much more effectively - they'd be rebasing without even necessarily knowing what rebasing was, for instance.
It also meant that the git workflow, if it was version controlled, could also be amended.
This worked out much better than the git course people were sent on.
> It's easier to figure out the various workflows you need
Fine, that might be cheaper than properly training your employees. Of course, if your employees aren't training themselves out of genuine interest that's really the only option.
But then once something goes wrong you'll have to resort to "oh shit" websites and hope that you can the exact issue that you're having, since you really don't understand what's going on anyway.
> This worked out much better than the git course people were sent on.
I submit this must be because people came out of the course without really understanding the tool. Why they didn't understand I won't speculate, but I submit that they didn't.
EDIT: I think that which one is more appropriate depends on where it's used. I a big structured company I can believe that yours is better, or even crucial. But on a scenario where I'm starting a company with two other guys on a garage, I wouldn't want the guys to be the type of people who can only use a workflow that someone designed for them and never had the interest to dig under.
Fine, that might be cheaper than properly training your employees. Of course, if your employees aren't training themselves out of genuine interest that's really the only option.
But then once something goes wrong you'll have to resort to "oh shit" websites and hope that you can the exact issue that you're having, since you really don't understand what's going on anyway.
> This worked out much better than the git course people were sent on.
I submit this must be because people came out of the course without really understanding the tool. Why they didn't understand I won't speculate, but I submit that they didn't.
EDIT: I think that which one is more appropriate depends on where it's used. I a big structured company I can believe that yours is better, or even crucial. But on a scenario where I'm starting a company with two other guys on a garage, I wouldn't want the guys to be the type of people who can only use a workflow that someone designed for them and never had the interest to dig under.
I tended to find that a few things were likely to go wrong and simply changing the git workflow scripts to account for those things was enough.
If things went wrong, people could come to me. That often resulted in me fixing their problem and fixing the script to ensure that kind of problem didn't happen again - after which people stopped coming to me because they didn't have problems.
Basically it was like releasing software.
>I submit this must be because people came out of the course without really understanding the tool.
I submit that not everybody needs to be an expert in the tool. Non-programmers can actually help a lot with writing stuff that needs to be version controlled with code - e.g. writing test scripts, updating translations, various configurations, etc.
If things went wrong, people could come to me. That often resulted in me fixing their problem and fixing the script to ensure that kind of problem didn't happen again - after which people stopped coming to me because they didn't have problems.
Basically it was like releasing software.
>I submit this must be because people came out of the course without really understanding the tool.
I submit that not everybody needs to be an expert in the tool. Non-programmers can actually help a lot with writing stuff that needs to be version controlled with code - e.g. writing test scripts, updating translations, various configurations, etc.
Is the documentation really that bad? Would it benefit from a technical writer going over it? Is the project open for discussion on changes to the documentation?
Git is like Perl. And not in any of the good ways.
Perl 5 -- I don't know enough about 6 to know whether this is still the case -- involved a couple of design decisions which worked well for one subset of people and did whatever the complete polar opposite of "works" is for a different subset of people.
One of those design decisions is the famous "there's more than one way to do it". Ask five Perl programmers to solve a simple problem in the language and you'll get fourteen solutions, and no way of knowing which, if any, is to be preferred in real-world use. Git similarly tends to have multiple ways of achieving a given goal, and endless words have been devoted to documenting them; nobody has yet settled which of them is or should be generally recommended, or if there even can be such things as generally-recommended ways to use git.
Perl also involves an incredible amount of memorization. The large collection of "magic" variables which can be read or set to determine language and local-scope behavior are daunting and can't be mastered through any process other than rote memorization. And the differing behavior of basic operations depending on context produces a combinatorial explosion of possibilities which, again, are not amenable to any technique short of rote memorization. The same is true in git: though there are underlying abstractions, the interface provided to them is inconsistent, varies depending on sometimes-invisible contextual factors, and ends up requiring rote memorization of commands and options and how they behave in any given situation.
Unfortunately, no amount of documentation or review by technical writers can fix this. A bad API can't be made good through better documentation, it can only be made good through being replaced with a better API.
Perl 5 -- I don't know enough about 6 to know whether this is still the case -- involved a couple of design decisions which worked well for one subset of people and did whatever the complete polar opposite of "works" is for a different subset of people.
One of those design decisions is the famous "there's more than one way to do it". Ask five Perl programmers to solve a simple problem in the language and you'll get fourteen solutions, and no way of knowing which, if any, is to be preferred in real-world use. Git similarly tends to have multiple ways of achieving a given goal, and endless words have been devoted to documenting them; nobody has yet settled which of them is or should be generally recommended, or if there even can be such things as generally-recommended ways to use git.
Perl also involves an incredible amount of memorization. The large collection of "magic" variables which can be read or set to determine language and local-scope behavior are daunting and can't be mastered through any process other than rote memorization. And the differing behavior of basic operations depending on context produces a combinatorial explosion of possibilities which, again, are not amenable to any technique short of rote memorization. The same is true in git: though there are underlying abstractions, the interface provided to them is inconsistent, varies depending on sometimes-invisible contextual factors, and ends up requiring rote memorization of commands and options and how they behave in any given situation.
Unfortunately, no amount of documentation or review by technical writers can fix this. A bad API can't be made good through better documentation, it can only be made good through being replaced with a better API.
I am a long-time Perl user and also a long-time Git user.
Git is worse than Perl. Perl is just opinionated: despite what you are saying about it is true, you can write working programs and have fun at all levels of Perl mastery. There's a lot to memorize, but you can start coding immediately and do something useful. Also, Perl community is incredibly friendly and helpful.
Not so with Git. If you start without thorough understanding how Git internals work, you will get burned really soon. And more often than not, the only response you'll get is the arrogant RTFM or the link to Pro Git book.
Git is worse than Perl. Perl is just opinionated: despite what you are saying about it is true, you can write working programs and have fun at all levels of Perl mastery. There's a lot to memorize, but you can start coding immediately and do something useful. Also, Perl community is incredibly friendly and helpful.
Not so with Git. If you start without thorough understanding how Git internals work, you will get burned really soon. And more often than not, the only response you'll get is the arrogant RTFM or the link to Pro Git book.
Good points. Also, git (not Perl though) was designed by a genius for himself (and a few other geniuses). All of whom don't know how much of a genius they are / don't comprehend how comparatively dumb the rest of us are. So, the git ui assumes you either "wrote git" or "have read the source and are smart enough to understand all it's implications".
[deleted]
Yep, git sucks but it's all the rage now. Mercurial is 100x nicer to use and logical, but since it's written in Python it's slow as molasses, especially with large binary files.
Next on the list: Larry McVoy's Bitkeeper promises to be everything git and Mercurial aren't. (git is "inspired" (read: copycat) by Bitkeeper).
It's funny how Sun Microsystems influenced the industry in so many ways, isn't it?
Next on the list: Larry McVoy's Bitkeeper promises to be everything git and Mercurial aren't. (git is "inspired" (read: copycat) by Bitkeeper).
It's funny how Sun Microsystems influenced the industry in so many ways, isn't it?
For anyone who wasn't aware, it's also open source these days - http://www.bitkeeper.org/
I understand that people need to know how to use their tools, but for git most people can get away with the very basic usage that GUIs provide. If you've made some unrecoverable mistake with an important set of changes, you can always review the history in the same GUI and reimplement the important changes in a new branch.