4 ms·
I never really understood Git until I read this tutorial: https://github.com/susam/gitpr https://github.com/susam/gitpr Things began to click for me as soon as
by chenhan 7y ago
I never really understood Git until I read this tutorial: https://github.com/susam/gitpr 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."
- phodge 7y ago> 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.
- jbnorth 7y agoI 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'.
- kortilla 7y agoIt 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.
- gruez 7y ago>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.
- Izkata 7y agoIt'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.
- rileymat2 7y agoThis 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.
- Mikhail_Edoshin 7y agoMercurial 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.
- Izkata 7y agoAnd 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)
- westurner 7y agoYou 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.txt-corepager 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).