Live data from Hacker News

Oh Shit, Git

ohshitgit.com

211–220 of 237 posts

Re: Oh Shit, Git

#211

I find people are religious about being git cli purists and only interacting with it in this black box (the terminal). On top of that a lot of people stop learning git after add commit push pull branch and merge so concepts like rebasing and cherry picking are scary. In this day and age we have state of the art GUI tools that change the game and allow git users to see and interact with the state of a git repository i…

The reason I learned about cherry picking, rebase & all is because when I tried using IntelliJ's UI to see my history, I saw a lot of options in the context menu and just searched what they meant.

It is also with a GUI that I learned you could rebase on pull, instead if merging and getting an ugly "Merged remote tracking changes" commit.

I encourage everyone I know to do this.

Re: Oh Shit, Git

#212
post #151
post #131

Earlier quoted context omitted.

> I find people are religious about being git cli purists […] we have state of the art GUI tools I would humbly suggest you avoid framing it that way, even if you believe it’s true. From someone who is only sometimes a cli advocate, my immediate assumption is that your opinion here may be formed out of naïveté and a bit of fear of the cli. Please note I’m actually quite a fan of using various GUI tools for basic git…

I'd really like to know what mess people make when they don't rebase. I've found that using merge gives a readable trail of when something was merged, whether that be from a branch's original branch, or if you're merging into another branch. Rebasing just seems to cause a lot more headache when something doesn't go perfectly correct in between commits.

> Rebasing just seems to cause a lot more headache when something doesn't go perfectly correct in between commits.

You mean merge conflicts? Rebase gives you an opportunity to deal with small merge conflicts arising from single commits. I much prefer that to a big merge commit dealing with all the conflicts simultaneously.

Also, rebase makes the merge conflicts disappear for future readers, making the included commits nicer to read.

Re: Oh Shit, Git

#213
post #151
post #131

Earlier quoted context omitted.

> I find people are religious about being git cli purists […] we have state of the art GUI tools I would humbly suggest you avoid framing it that way, even if you believe it’s true. From someone who is only sometimes a cli advocate, my immediate assumption is that your opinion here may be formed out of naïveté and a bit of fear of the cli. Please note I’m actually quite a fan of using various GUI tools for basic git…

I'd really like to know what mess people make when they don't rebase. I've found that using merge gives a readable trail of when something was merged, whether that be from a branch's original branch, or if you're merging into another branch. Rebasing just seems to cause a lot more headache when something doesn't go perfectly correct in between commits.

I'm someone who has started enjoying rebasing workflow after using branch-merge workflow for more than a decade. So perhaps, my experience may be useful since you can compare the same person using both of them. The first thing to realize is that branch-merge and rebase workflows try to achieve different goals. Branch-merge tries to preserve history of the code, with every wart and quirk included. Rebase tries to achieve a clean history where every commit is an entire fully functional (without known errors) feature with complete explanation in the commit message. People fight over them, but I find both goals to be meaningful and the choice depends on your priorities. In fact, I do both- publish a clean history in the master and the original messy history as a separate branch.

> I'd really like to know what mess people make when they don't rebase.

As a developer, we have the expectation that git will allow us to experiment with features, make mistakes, correct them, roll them back and improve. That stage is also so messy that you'd leave short commit messages that would make sense only to you. This is fine while developing. But this leaves many commits that are functionally broken, partial or rolled back later. That, along with vague commit messages and illogical commit order make it really hard for someone else to pick up a working commit from your branch and continue. Heck! I find it hard to choose a commit even from my own older repositories. That isn't the case with good projects like the kernel. You can pick any commit on the master and it will compile and work with all the features advertised up to that commit message. It makes a users' life easier.

> I've found that using merge gives a readable trail of when something was merged, whether that be from a branch's original branch, or if you're merging into another branch.

This is true. It's harder to achieve with rebasing. But it's possible with some work. I usually leave the original messy feature branch intact, and mark the rebased HEAD with a similar-worded tag or branch.

> Rebasing just seems to cause a lot more headache when something doesn't go perfectly correct in between commits.

Don't take any offense, but those are beginner blues. It happens in the early stage of learning rebases when you don't have a full grasp of what is going on. People evolve different strategies to overcome this once they are a bit more comfortable. My strategy is to create a temporary branch for rebasing (at the same commit as the feature branch) and do multiple rebases on it. I do only one or maximum two operations during each rebase. The result of each rebase is reviewed before doing the next round of rebase on the same branch. The original feature branch is left intact in case something goes wrong - though I never needed it.

Other people do rebasing occasionally while developing the branch. They do this after every two or three commits. They end up with a clean history to merge (fast-forward) to master, by the time they finish the branch. All of these operations can be simplified using helper tools like git-revise [1].

My absolute favourite method is to not use rebase at all. Craft the perfect commits as you develop. This can be achieved with a patch stack tool like quilt or stacked-git [2]. It allows you to move your changes to a patch (commit) of your choice. This is like having multiple staging indexes available. You can also split, combine or reorder patches. The patch stack evolves as you develop, but you end up with a perfect history to merge (fast-forward) at the end.

[1] https://github.com/mystor/git-revise/

[2] https://stacked-git.github.io/

Re: Oh Shit, Git

#214

I find people are religious about being git cli purists and only interacting with it in this black box (the terminal). On top of that a lot of people stop learning git after add commit push pull branch and merge so concepts like rebasing and cherry picking are scary. In this day and age we have state of the art GUI tools that change the game and allow git users to see and interact with the state of a git repository i…

Some operations lend themselves well to a graphical interface, such as partial staging and interactive rebasing. Others might not. As long as you show and read before pushing to a remote repository, the worse you can do is create extra work for yourself. However I'm not sure Kraken is a good example. The GUIs for git are all similar, but Kraken has some unfortunate combination of being counter intuitive at times, and…

> Some operations lend themselves well to a graphical interface, such as partial staging and interactive rebasing

I can't emphasize how pleasant those operations are in magit. I'm not sure if it (TUI) would be considered as textual or graphical. However, the interface model should lend well to a fully graphical implementation.

Re: Oh Shit, Git

#215

I find people are religious about being git cli purists and only interacting with it in this black box (the terminal). On top of that a lot of people stop learning git after add commit push pull branch and merge so concepts like rebasing and cherry picking are scary. In this day and age we have state of the art GUI tools that change the game and allow git users to see and interact with the state of a git repository i…

Intellij diff helps me keep my sanity when I merge with conflicts

Re: Oh Shit, Git

#216
post #45

Earlier quoted context omitted.

Git's UI/UX is one of the worst engineering sins to be committed in the last two decades, and this website shows why. Literally nothing about git is intuitive and the "underlying model" is entirely ad-hoc. Instead of celebrating how Linus built git in only a few days he should be castigated for knowingly setting up ill-conceived software to go viral.

I think the underlying model is fantastic, but the names for operations, and how they are grouped, are somewhat ad hoc. The idea of a directed graph of file system snapshots is pretty intuitive. Add in branches as pointers to locations in that graph. This is a fantastic model for source control. However the operations that stage a potential update to the graph of snapshots is prettt confusing. The "index" is a terrib…

> I think the underlying model is fantastic

The well-documented underlying model used to confuse me a lot - especially for operations like merging, rebasing (squash, reorder, ...), cherry picking, etc. They started to make sense only when I realized that git uses diffs/patches to propagate changes between unrelated commits. While the on-disk format is purely snapshot-based, the tool itself is a hybrid. As far as I can tell, this trips up a lot of others too.

Re: Oh Shit, Git

#217
post #157
post #72

Earlier quoted context omitted.

> It dominated the world thanks to Linus cult (their hero can do no wrong), and being required for Linux contributions. I think parent's point is that that demographic is positively tiny , and there were plenty of other serviceable offerings around at the time. The claim stands - git won despite its UX flaws, which does suggest the alternatives, while serviceable, weren't sufficiently fit for purpose.

The alternatives weren't required for collaboration in Linux development.

Yes, but again, the number of people collaborating on Linux kernel development is truly tiny.

I think perhaps you're over-estimating the network effect for VCS's -- having multiple version control binaries on your machine is low cost, and aliases can, up to a point, give you a consistent interface to them all.

The highly sophisticated demographic of kernel developers would not have been at the pub insisting that their friends drop svn and use git (exclusively!), anymore than they would have been trying to get any other projects they worked on to adopt bitkeeper previously.

The fact that bitkeeper was required for 'collaboration in Linux development' for so long supports this position.

Re: Oh Shit, Git

#218

Earlier quoted context omitted.

Not sure what origin/HEAD is supposed to point to. HEAD is a ref that points to the tip of the current branch. It's not going to be available for remotes (it just doesn't make sense). To reset the current branch, you need to do two things: $ git fetch to fetch commits from the default remote and point remote branches accordingly, and $ git reset --hard origin/master to reset HEAD to the remote branch. Substitute mast…

I don't know what the difference is, honestly :( I believe you, but I see both online and nobody seems to know the difference and it seems to work. Shrug? Most of my git life is copy pasting somebody else's commands because the model of it is really too complex for me. I've given up on caring... it's easier and faster to rewrite some code than deal with git's commands. Same thing for node modules, lol. Delete the fol…

Two things to make sense of how origin/HEAD is working.

First is that HEAD always points to the commit that you currently have checked out. So, for example, if you have the master branch checked out, HEAD will be whatever is the latest commit in master in your local copy of the repository.

Second is that to git there is no difference between the originating repository and your own. If you had your copy of the repo fully exposed, the remote machine that you cloned it from could push changes to your copy exactly the same way that you push changes to the remote machine.

That second part is important because it means that the remote machine you're pulling from also has its own HEAD pointer. When you reset your state to origin/HEAD, you're telling git to set your own HEAD to point to the same thing as the remote machine's HEAD. This is very likely to be the same asking it to reset to origin/master because HEAD is probably pointing to master on the remote machine.

The reason it's likely that HEAD=master is that in most circumstances the repo on the remote machine isn't manually being touched. When you first setup a repo there is only a single branch so that is what HEAD points to. If no one ever logs into the machine and executes a checkout command, that's what the server is going to continue to point to.

However since there's no guarantee that HEAD=master, you shouldn't rely on that and instead always use the actual branch name.

Re: Oh Shit, Git

#219
post #206

Earlier quoted context omitted.

It may not have sounded like it but I'm actually going to agree with some of this. We might be on a different part of the gradient so to speak. Maybe you can find a good analogy but at least from my point of view the gearbox analogy is falling short now and we'd need a different one or look at git commands one by one :) Like you say, you can just remember those things. In fact 4 out of those 6 were taught in driving…

You're absolutely right, there are about a million and one rabbit holes you can go down if you _really_ want to understand the tools you use but in the vast majority of those cases you're better off relying on a higher level abstraction. The interesting part to me of your analogy is that it can demonstrate how having an understanding of what's going on under your layer of abstraction allows you to generalise. To wrin…

> That understanding lets me generalise to, for example, backing up a branch (with git branch/tag) before doing a tricky rebase so I can restore it (with git reset --hard) if I need to undo.

You can also do `git reflog` on branches to see what they used to point to :)

Re: Oh Shit, Git

#220

> # remove the last commit from the master branch > git reset HEAD~ --hard I see this all the time, this "commits ON a branch" mentality. My secret to understanding git is: branches are just adresses, labels, pointers, aliases to commits. A branch is just a label pointing to a commit. So, you don't "remove (or add) a commit from a branch", you change where a branch point to. Commits are tree nodes, they have a parent…

>...So, you don't "remove (or add) a commit from a branch", you change where a branch point to. Well, once committed, the corresponding deltas to parent are part of the branch (that is a node of the branch graph). Thus, if user wants to have this commit in a different graph, then the deltas need to be regenerated and recommitted (then deleted from the wrong graph). As for the branch name , in Git it's just a label fo…

> Well, once committed, the corresponding deltas to parent are part of the branch (that is a node of the branch graph).

Not sure what you mean by deltas here, but if you are taking about changes, git don’t store changes, each commit references the state (the content) of the whole repository.

The diffs are just a representation calculated to you.

Like: `git show ` shows a diff, but actually what happens is that git calculates the difference between all repository’s files as they were (their contents) in commit A vs their contents in commit B.

Git does that in a very efficient way, but commit are actually snapshots.

Post reply on HN