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."
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) #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).
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.
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.
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.
But this is not actually correct because a branch can often point to a commit that is not the tip.
The point is that a branch is simply a pointer to a commit that automatically encapsulates all of the parent commits.
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.
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.
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\""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)
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.
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.
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.
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.