Hacker News new | past | comments | ask | show | jobs | submit login

> the supposedly obtuse interface makes a lot more sense when you approach it with an understanding of the fundamentals in hand.

Agreed. I always said the best git tutorial is https://www.sbf5.com/~cduan/technical/git/

> The conclusion I draw from this is that you can only really use Git if you understand how Git works. Merely memorizing which commands you should run at what times will work in the short run, but it’s only a matter of time before you get stuck or, worse, break something.




I never really understood Git until I read this tutorial: https://github.com/susam/gitpr

Things began to click for me as soon as I read this in its intro section:

> Beginners to this workflow should always remember that a Git branch is not a container of commits, but rather a lightweight moving pointer that points to a commit in the commit history.

    A---B---C
            ↑
         (master)
> When a new commit is made in a branch, its branch pointer simply moves to point to the last commit in the branch.

    A---B---C---D
                ↑
             (master)
> A branch is merely a pointer to the tip of a series of commits. With this little thing in mind, seemingly complex operations like rebase and fast-forward merges become easy to understand and use.

This "moving pointer" model of Git branches led me to instant enlightenment. Now I can apply this model to other complicated operations too like conflict resolution during rebase, interactive rebase, force pushes, etc.

If I had to select a single most important concept in Git, I would say it is this: "A branch is merely a pointer to the tip of a series of commits."


And you can see this structure if you add to any "git log" command "--graph --oneline --decorate --color". IIRC some of those are unnecessary in recent versions of git, I just remember needing all of them at the point I started using it regularly.

I have a bash function for it (with a ton of other customizations, but it boils down to this):

  function pwlog() {
    git log "$@" --graph --oneline --decorate --color | less -SEXIER
  }
  pwlog --all -20
(...in that "less" command, "S" truncates instead of wraps lines, one "E" exits at EOF, "X" prevents screen-clearing, and "R" is to keep the color output. The second "E" does nothing special, it and "I" (case-insensitive search) are just to complete the word)

You can also set $GIT_PAGER/core.pager/$PAGER and create an alias to accomplish this:

  #export PAGER='less -SEXIER'
  #export GIT_PAGER='less -SEXIER'
  git config --global core.pager 'less -SEXIER'
  git config --global alias.l 'log --graph --oneline --decorate --color'
  # git diff ~/.gitconfig
  git l
core.pager: https://git-scm.com/docs/git-config#Documentation/git-config...

> The order of preference is the $GIT_PAGER environment variable, then core.pager configuration, then $PAGER, and then the default chosen at compile time (usually less).


>This "moving pointer" model of Git branches led me to instant enlightenment.

As opposed to any other VCS? Feels like that model is the only one that works with SVN too. I struggle to see how "branch is a container of commits" is a viable model to begin with.


It's a good-enough description of SVN, where branches exist in the same directory tree, commits are tied to the branch by way of the path, and the merge tools are "merge this batch of commits from branch A to trunk" (you don't have to take the whole branch at once).

One of the biggest hurdles my co-workers have had learning git after having used svn for years is the "bucket of commits" mental model they've built up for branches. A common question is how to merge a single commit.


This is closer to how I would describe HG and SVN. Branches can be traced from start to merge, they are heavy. You know which commits came from what.

In git you can lose track of what came from what branch when you start merging multiple back and forth, this does happen with svn.


Mercurial branches are different from git branches; they're topological structures that emerge when a revision gets an alternate child. They're like growing and stopping lines of development. They exist on their own, Mercurial simply allows to give them names. What git calls branches in Mercurial is called bookmarks.

> A branch is merely a pointer to the tip of a series of commits.

But this is not actually correct because a branch can often point to a commit that is not the tip.


It is the tip for that branch. Even if there exist other commits building on the commit the current branch points to, the pointer is still at the tip for that branch.

The point is that a branch is simply a pointer to a commit that automatically encapsulates all of the parent commits.


I think I see what it means though. The branch uses that commit as a new tip to then branch off of, not necessarily meaning a new branch starts at the existing 'tip'.

>The conclusion I draw from this is that you can only really use Git if you understand how Git works.

I say this as someone who uses git regularly, and who prefers it to all other version control systems I have tried:

A tool that breaks the principle of encapsulation by forcing you to grok its internals if you are to have any hope of understanding its arcane and inconsistent usage syntax is frankly not a very good tool.

By contrast, I don't understand how vim works beyond the base conceptual level (keypress goes in, character shows up on screen or command is executed) and yet I don't have any trouble using it. I don't need to know vim's internals to use it effectively. Vim is a good tool.


> I don't understand how vim works beyond the base conceptual level

How much time have you spent trying to figure out how to change the font size in Vim, rotate text 90° in Vim, recalculate a formula in Vim, or insert an image into a document you're editing in it? If the answer is “none”, you probably have a pretty deep understanding of the data model Vim manipulates, even if you aren't aware of it.


On the other hand I understand de data model of git and can't to the most basic shit without looking up which invocation I need via search engine/man pages. Like... deleting a branch `git branch -d` (-D for forced deletion). Deleting a remote? `git remote rm`. Knowing the model teaches me nothing about the ui.

This seems like a good opportunity to plug two aliases I wrote about a year ago that have been very helpful for cleaning up all the extraneous branches that would show up when I ran `git branch`.

I run `git listdead` after I merge and delete a branch and do the next fetch (`git pull --rebase`). That lists the branches that can now be deleted.

Then I run `git prunedead` and it actually removes them.

Previously if I ran `git branch` it would list every development branch I had ever created in nearly a decade of work. Now it lists maybe ten branches.

   listdead = "!sh -c \"git branch -vv | grep ': gone]' | awk '{print \\$1}'\""

   prunedead = "!sh -c \"git branch -vv | grep ': gone]' | awk '{print \\$1}' | xargs git branch -D\""

Myself, I frequently refer to the man pages, as well as StackOverflow.

> rotate text 90° in Vim, recalculate a formula in Vim, or insert an image into a document you're editing in it

I'm not sure if I'm missing some features in Vim or you're actually pulling my leg by forcing me to notice that I know more about text than I care to admin :-)

(I'm not OP, BTW, just a random passer-by)


The latter! Sorry, didn't mean to cause you to question your sanity.

Using Vim requires you to understand how the data it operates on is structured. The same applies to Git. Plain text is just a lot simpler than a VCS repository.


But you can use your awesome vim skill to feed text into a OpenOffice document, and while the OOo internals are probably 100x more complicated than vim, the user interface for "text on my screen" stays the same, and transition is smooth, even though the internals underneath is vastly different. If git requires 'everyone' to know the internals before they can use it, as opposed to rcs,cvs,svn,perforce users who can more easily flip around between those for most basic usages, then its on git for having a complicated shell around a complicated set of internals.

It would have been nice if there was a simpler shell around the complex machinery for those (us?) who don't want to do crazy stuff, who don't need to be able to do crazy stuff and who could settle for only the simple 90% of the tooling like we do with the alternatives, but are forced to use git for external reasons.


Plain text is internally ropes-something, indented with meters of vimscript, colored with a syntax model that is okay to change, hard to create from scratch, etc. it’s all hidden from a regular user who uses a subset of all features.

But if you ignore the non-ms movement, shortcuts and advanced transforms, it is still a text editor that everyone may use. You can’t put your text (text, not a current mode!) into a state that looks okay but requires a vim guru to continue or start over because something is broken in the model. That’s different from git issues where working copy looks okay, but the branch and merge are broken in subtle ways.

>Plain text is just a lot simpler than a VCS repository.

Than a Git repository, not a VCS one. Not saying that VCS = plain text, but much simpler models exist for merging teh codes.


Scott Chacon wrote a book on git internals that was published by peepcode some time ago. Searching for where to buy it turned up this HN thread: https://news.ycombinator.com/item?id=7999515

Looks like peepcode was acquired, but the book was open sourced: https://github.com/pluralsight/git-internals-pdf

I'm reading through it now. It starts with the fundamental git structure and works up from there.




Applications are open for YC Summer 2020

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: