[OT] Question about Git branches

Sergey Organov sorganov at gmail.com
Wed Sep 17 14:04:48 CEST 2014


"Frank Millman" <frank at chagford.com> writes:
> Hi all
>
> I know there some Git experts on this list, so I hope you don't mind me 
> posting this question here.
>
> I am slowly getting comfortable with Git, but there is something that 
> confuses me.

If you want to be really comfortable with Git, you need to understand
basics of its rather simple underlying data model. Find a toutorial that
discusses this, and things will start to take their natural places.

You need to become aware that from Git point of view, your project
history is a DAG of commits, and branches are just pointers to specific
nodes of the DAG. It's very essential, so I repeat: "branch" in Git is
nothing more than a named pointer to specific commit in the DAG.

You should also learn that the files you are changing constitute
"working tree", and working tree does not belong to the DAG (and
therefore to any branch). Git simply remembers particular commit in the
DAG the working tree is checked-out from in the special HEAD pointer
(that usually points to the current branch, that in turn points to the
commit).

> You are encouraged to make liberal use of 'branches', and if required you 
> can have multiple branches running concurrently.

I'm afraid "multiple branches running concurrently" could be rather
confusing. Recalling that Git branches are just pointers, they don't
"run", they just exist. One needs to clearly understand the difference
between Git branch, being a pointer to a commit, and the sequence of
commits that lead to the commit at which Git branch points. When we say
"branch of development", we usually mean the latter, and when we run
"git checkout <branch_name>" we should understand we mean the former.

> When you commit changes on one branch, 

Strictly speaking, when you commit, you don't commit changes, you create
commit that contains entire state of your tree, and then this new commit
is attached to the DAG where current branch points to. Then current
branch is changed to point to this new commit.

> those changes are not visible to other branches

Exaclty. Any commit in the DAG is either reachable or not from given
branch when history is traversed backwards. That's how "visible" is
defined in Git. Right after commit is made, it's only reachable from the
current branch (if any) indeed.

> until you merge,

Exactly. When you merge a branch to another branch, all commits
reachable from the "branch" become reachable from "another branch" as
well.

> so each branch can be worked on independently.
>
> However, if you are working on a branch and make some changes, those changes 
> are visible to *all* branches until you commit.

No, as they are not in the DAG yet, they are not reachable from any
branches, so they are not visible to any of them.

What you see are changes in your working tree with respect to the commit
that is currently checked-out (usually those one to which the current
branch points).

> If you run 'git status' from any branch, you can see all files that
> have been modified or added.

You don't run 'git status' on a branch. You run it from within
repository/working tree, and then repository (usually) has some specific
branch being current at the time of invokation of 'git status' that 'git
status' will report as such.

> It seems to me that this can be confusing. When you are ready to commit 
> changes on one branch, you have to -
>   - check that it is the currently checked-out branch, which is not always 
>     obvious

What exactly "it" means in the "it is the currently..." above? Do you
mean you need to check that the current branch is those one you want to
commit changes into? If so, ask youself why do you do changes to a state
of your working tree that was checked out from any other branch in the
first place?

Usually, you checkout a branch, make changes and commit them. Only if
you realize that you was (and still are) on the wrong branch, you need
to switch branches, and Git allows you to take your changes along with
you, exactly what you need in this case.

If what you want is to temporarily stop working on these particular
changes and visit (checkout) another branch, you can stash your changes
using "git stash" and restore them later, or you can commit the changes
(remember that commits are local unless you publish them), and then,
after you return to this branch later, use, e.g., "git reset HEAD~1" to
continue editing your changes, or you can just edit further and then
commit the changes as the new commit, or amend those temporary commit
with your new changes ("git commit --amend").

>   - choose which altered files you want to add to the staging area
>   - stage them and then commit

You rather usually choose them by adding them to the staging area
(unless we talk about some GUI on top of Git), so it rather looks like:

- choose which changes you want to commit by adding them to the
  staging area.
- commit.

You can often bypass staging by "git commit -a", but anyway, "staging
area" or "index" is yet another thing in Git it's better to make
yourself familiar with, as you won't be able to ignore it if you ever
reabase or merge.

> This seems error-prone. Am I missing something?

What exactly is error-prone? Are you afraid to commit to a wrong branch?
Are you afraid to commit the changes you didn't want to commit? Anyway,
if you did a mistake, you should be able to examine situation and fix it
rather easily, provided you didn't yet publish your history.

HTH,

-- Sergey.



More information about the Python-list mailing list