I'm a git novice and have a comprehension question concerning branches.
Within a git repository, I do:
git branch test
git checkout test
# edit foo.bar
git checkout master
I'd expect that master is in the exactly same unchanged state it was at
branching time, but what a surprise, foo.bar is modified here, too!
If I continue now working in the master branch (applying patches and such) I
will use a changed foo.bar with testing branch content. I can't even apply
patches to foo.bar without conflict.
Of what use are branches if the files aren't totally separated from each
other?
What must I do to get a test branch I can't work without affecting master?
Ingo
On Wed, Aug 19, 2009 at 5:33 PM, Ingo Brueckl[off-list ref] wrote:
Within a git repository, I do:
git branch test
git checkout test
# edit foo.bar
git checkout master
I'd expect that master is in the exactly same unchanged state it was at
branching time, but what a surprise, foo.bar is modified here, too!
You seem to have forgotten the "git commit" step before switching back
to master. You have a modified file in your repository; what did you
*want* to happen when you switched branches? (Many people find the
current behaviour very convenient.)
You might also want to look at the "git stash" command.
Avery
You seem to have forgotten the "git commit" step before switching back
to master.
No, I passed over the commit in my example. I know that after the commit the
things are as they ought to be, but what if I can't do a commit because I am
in the middle of coding and have to have a break?
You have a modified file in your repository; what did you *want* to happen
when you switched branches?
I want an unchanged file in master if I switch there (because I worked in a
different branch) and a changed version in the test branch.
Why is the *master* different depending on whether my work in test in still
going on or committed?!
Actually, I cannot image how branches are practicable if I always have to
have in mind possibly still uncommitted work. Shouldn't it be git's work
to ensure that master will remain it was when branching?
Without git I'd make a copy for testing new features. With git, it seems that
I have to do the same (a clone). This is what I don't understand.
(Many people find the current behaviour very convenient.)
I find it highly confusing. I understood a branch as something I can do in
whatever I want without affecting master. But now a learn that everything I
do in the branch will happen in master, too, until I commit. Strange. Very
strange.
You might also want to look at the "git stash" command.
Yes, but isn't it annoying to leave the test branch always either with stash
or commit in order to have an unchanged master?!
Ingo
From: Jakub Narebski <hidden> Date: 2016-06-15 22:47:17
ib@wupperonline.de (Ingo Brueckl) writes:
Avery Pennarun [off-list ref] writes:
quoted
You seem to have forgotten the "git commit" step before switching back
to master.
No, I passed over the commit in my example. I know that after the commit the
things are as they ought to be, but what if I can't do a commit because I am
in the middle of coding and have to have a break?
Then you use git-stash. It was invented for that.
quoted
You have a modified file in your repository; what did you *want* to happen
when you switched branches?
I want an unchanged file in master if I switch there (because I worked in a
different branch) and a changed version in the test branch.
Why is the *master* different depending on whether my work in test in still
going on or committed?!
Branches are about commits. State of a working directory doesn't
belong to a branch (in Git). Learning concepts behind Git would help
you in understanding it (Git is very consistent), which in turn would
help in using it.
What about untracked files? Do you want to lose them when you switch
branches?
Actually, I cannot image how branches are practicable if I always have to
have in mind possibly still uncommitted work. Shouldn't it be git's work
to ensure that master will remain it was when branching?
Without git I'd make a copy for testing new features. With git, it seems that
I have to do the same (a clone). This is what I don't understand.
You finish old work (or stash it away), _then_ you begin new work.
quoted
(Many people find the current behaviour very convenient.)
Take the following example. You started coding some feature on
'master' branch, then you realized that this feature is more
complicated than you thought at first, so it should be developed in
separate topic branch. You do "git checkout -b featureA", and voila
you are now coding on feature branch 'featureA'.
quoted
You might also want to look at the "git stash" command.
Yes, but isn't it annoying to leave the test branch always either with stash
or commit in order to have an unchanged master?!
You finish old work (or stash it away), _then_ you begin new work.
Ok, this helps me a little bit to understand.
The branches aren't designed to split my work, but rather something to
collect the different parts of my work.
But as software development often is something where you are coding on
several issues at the same time which can't be committed immediately, it
sounds that 'stash' is the developer's best friend.
Ingo
On Wed, Aug 19, 2009 at 7:45 PM, Ingo Brueckl[off-list ref] wrote:
Jakub Narebski [off-list ref] writes:
quoted
You finish old work (or stash it away), _then_ you begin new work.
Ok, this helps me a little bit to understand.
The branches aren't designed to split my work, but rather something to
collect the different parts of my work.
But as software development often is something where you are coding on
several issues at the same time which can't be committed immediately, it
sounds that 'stash' is the developer's best friend.
Or you could just 'commit' more frequently, but don't 'push' so you're
not disturbing anyone else until you're done.
This is a big difference from how centralized VCSs work: there, a
commit is a major operation that you're afraid to do in case you make
someone else mad. In git, commits are cheap, you just need to be
careful about pushing.
(You can also clean up your series of commits before pushing by using
'git rebase')
Have fun,
Avery
From: Jacob Helwig <hidden> Date: 2016-06-15 22:47:17
On Wed, Aug 19, 2009 at 12:45, Ingo Brueckl[off-list ref] wrote:
But as software development often is something where you are coding on
several issues at the same time which can't be committed immediately, it
sounds that 'stash' is the developer's best friend.
Ingo
There is no problem with having temporary commits on local branches,
however.
Quite frequently, I'll "git commit -a -m 'Temp commit'; git checkout
other-branch". As long as you don't make these temporary commits
public, it's very easy to munge them (See: "git rebase --interactive
<commitish>", and "git reset --soft <commitish>").
-Jacob
From: Jakub Narebski <hidden> Date: 2016-06-15 22:47:17
On Wed, 19 Aug 2009, Ingo Brueckl wrote:
Jakub Narebski [off-list ref] writes:
quoted
You finish old work (or stash it away), _then_ you begin new work.
Ok, this helps me a little bit to understand.
The branches aren't designed to split my work, but rather something to
collect the different parts of my work.
Well, git is flexible enough that it can support also the workflow you
tried to use.
Namely you can have many working directories tied to single repository
(each of those checkouts should be of different branch). You can use
git-new-workdir script from contrib/worktree for that. Then to switch
branches you would just cd to appropriate directory (and keep unsaved
changes and untracked files). That said it is [much] less used
workflow.
But as software development often is something where you are coding on
several issues at the same time which can't be committed immediately,
it sounds that 'stash' is the developer's best friend.
Well, you can also commit and then clean up history with interactive
rebase (or patch management interface such as StGit or Guilt). In
distributed version control systems like Git the act of publishing
changes is separate from the act of committing them (you should not
rewrite published history, though).
--
Jakub Narebski
Poland
On Wed, Aug 19, 2009 at 09:45:00PM +0200, Ingo Brueckl wrote:
Jakub Narebski [off-list ref] writes:
quoted
You finish old work (or stash it away), _then_ you begin new work.
Ok, this helps me a little bit to understand.
The branches aren't designed to split my work, but rather something to
collect the different parts of my work.
But as software development often is something where you are coding on
several issues at the same time which can't be committed immediately, it
sounds that 'stash' is the developer's best friend.
Context switching has overhead; so it's usually better to try to
complete one task before switching to another. Granted, sometimes it
can't be done, but it's something you should really try to do.
Also, commits are easier to review if they are kept small; if you
localize changes into separate commits, it's often easier to detet
problems when doing "git bisect", for example. So if you are often
needing to switch while leaving something that isn't ready to be
committed, you might want to ask yourself if you are putting too many
changes into a single ocmmit.
Personally, in the cases where I can't finish a commit before I need
to switch away to another branch, my preference is to not use "git
stash", but instead to create a topic branch, and then check in a
partially completed change on the topic branch, which I can later
ammend using "git commit --amend" (or if I have multiple commits on
the topic branch, "git rebase --interactive"). This is because I can
use the commit description to leave myself some notes about what still
needs to be done before the commit can be finalized.
- Ted
From: Jakub Narebski <hidden> Date: 2016-06-15 22:47:17
Theodore Tso wrote:
Personally, in the cases where I can't finish a commit before I need
to switch away to another branch, my preference is to not use "git
stash", but instead to create a topic branch, and then check in a
partially completed change on the topic branch, which I can later
ammend using "git commit --amend" (or if I have multiple commits on
the topic branch, "git rebase --interactive"). This is because I can
use the commit description to leave myself some notes about what still
needs to be done before the commit can be finalized.
Errr... you are aware that you can use "git stash save <message>" (i.e.
specify commit message for stash; well, the subject), don't you?
--
Jakub Narebski
Poland
You finish old work (or stash it away), _then_ you begin new work.
Ok, this helps me a little bit to understand.
The branches aren't designed to split my work, but rather something to
collect the different parts of my work.
Hmm. Yes. That's one way of looking at it.
At the same time, thinking about it another way may explain the git
choices in this area. There's two issues:
- if we _don't_ carry the edits around across branch switches, then what
would we do?
Basically, since you haven't committed things, it's kind of floating
around. You switch to another branch, what should we do? There are
really only two choices: either we'd need to 'stash' the state with the
branch we switch away from (which is apparently what you expected), or
we need to just move the changes to the new branch (which is what git
does, or complains if it cannot).
Now, 'stashing' the changes is actually very much against the whole git
philosophy. Git was built up around the index and the database, and
branches have always been pointers to the top-of-commit, so there
literally isn't any way to stash things that makes sense. Sure, later
on we ended up having the 'stash' command, but that's totally separate
from branches, and is an independently useful thing.
- One of the big reasons to act like git does is that the way at least
_I_ work is to actually create a new branch with the explicit intention
of committing work I have already done!
IOW, your example was
git branch test
git checkout test
# edit foo.bar
git checkout master
and you were surprised that the edit followed you back to the "master"
branch, but what is actualyl a much more natural way of working is
# edit foo.bar
# realize that this was actually the start of a new feature
git branch new-feature
git checkout new-feature
# maybe continue to edit foo.bar until it's all good
git commit -a
ie the git behavior explicitly _encourages_ you to not have to decide
before-the-fact to create a branch - it may be that only after you've
done the changes do you realize that "oops, these changes were _way_
more intrusive than I originally anticipated, and I don't want to
commit them on the master branch, I want to commit them on an
experimental topic branch instead"
So there are two different reasons why git works the way it does: a pure
implementation reason ("working any other way would not fit the git
model") and a practical workflow reason ("you are _expected_ to move dirty
state around with your branches, because one common case is to create a
branch _for_ that dirty state").
Linus
branches have always been pointers to the top-of-commit
Obviously I expected them to be pointers on trees.
A kind of automatical starting commit in a newly created branch would at
least warn if one has begun changing files and wants to checkout back.
(Is this a feature worth of discussion?)
the git behavior explicitly _encourages_ you to not have to decide
before-the-fact to create a branch
Thanks for the explanation which help me to understand why git works like it
does.
I'm able to follow your examples, but what I had it mind when I started the
topic and my example was:
Assume a project is released (i.e. no more open bugs we know about) - I know
we're drifting towards fantasy now. ;-)
On the one hand, I want to add single new features (such as other developers
do) which will be written, tested and committed. I want to push/pull
frequently to be up to date all the time. (master branch)
On the other hand, I want to completely rewrite the core of the program.
(test or rewrite branch)
What is the git way to do this in a the right (and clever) manner?
In a branch, I learned, I have to commit or stash before I return to master
for push/pull to follow the project. If I forget, I'm screwed, because files
have changed due to the rewrite (in that branch), I won't get a warning until
my first commit (in that branch) and commits (in master) will conflict.
Ingo
From: Johannes Sixt <hidden> Date: 2016-06-15 22:47:17
[Please don't cull the Cc list.]
Ingo Brueckl schrieb:
On the one hand, I want to add single new features (such as other developers
do) which will be written, tested and committed. I want to push/pull
frequently to be up to date all the time. (master branch)
If you want to stay up-to-date while you are creating a new feature, then
your workflow is sub-optimal. This message by Linus is good to read:
http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html
The important rule is "Don't merge upstream code at random points".
Once you learnt this rule, then you also see that it is not important to
always stay up-to-date. It is important to complete (test, debug) your
feature on a stable base. During that time, you don't care about upstream;
you care about your feature.
In a branch, I learned, I have to commit or stash before I return to master
for push/pull to follow the project. If I forget, I'm screwed, because files
have changed due to the rewrite (in that branch), I won't get a warning until
my first commit (in that branch) and commits (in master) will conflict.
You are obviously of a CVS or SVN mindset, where making a commit is such
an important operation that you don't dare to make it until your work is
*completed*.
With a git mindset, it won't happen that you "forget" whether you have
anything uncommitted; you simply never have because committing half-baked
stuff is the rule, not the exception. That is, before you get a cup of
coffee, you commit; before you answer a phone call, you commit; before you
turn your attention away, you commit. (That may be exaggerated, perhaps it
even isn't, but you get the point.)
When you have completed your work, you go back to make your commit history
look nice, comprehensible, and bisectable.
And only then comes the heavy operation: You publish your work for
consumption by interested parties. This may be even only you yourself:
"Consumption" would be to merge the work into your release branch. This is
the right time to care about upstream again.
-- Hannes
From: Jakub Narebski <hidden> Date: 2016-06-15 22:47:17
Johannes Sixt [off-list ref] writes:
Ingo Brueckl schrieb:
quoted
In a branch, I learned, I have to commit or stash before I return to master
for push/pull to follow the project. If I forget, I'm screwed, because files
have changed due to the rewrite (in that branch), I won't get a warning until
my first commit (in that branch) and commits (in master) will conflict.
Errr... if having unknown files in status info when comitting doesn't
clue you in that you have spurious uncomitted changes,
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: somefile
and neither commit diff summary
n files changed, kk insertions(+), ll deletions(-)
doesn't clue you in, then you have more serous problems!
Second, you can use git-aware prompt to tell you if you have
uncomitted changes, so you will know when switching branches that you
have some changes that don't belong to branch you switch from.
You are obviously of a CVS or SVN mindset, where making a commit is such
an important operation that you don't dare to make it until your work is
*completed*.
With a git mindset, it won't happen that you "forget" whether you have
anything uncommitted; you simply never have because committing half-baked
stuff is the rule, not the exception. That is, before you get a cup of
coffee, you commit; before you answer a phone call, you commit; before you
turn your attention away, you commit. (That may be exaggerated, perhaps it
even isn't, but you get the point.)
When you have completed your work, you go back to make your commit history
look nice, comprehensible, and bisectable.
...with "git rebase --interactive" or patch management interface
(StGit, Guilt), or topic branch management interface (TopGit).
And only then comes the heavy operation: You publish your work for
consumption by interested parties. This may be even only you yourself:
"Consumption" would be to merge the work into your release branch. This is
the right time to care about upstream again.
On Wed, Aug 19, 2009 at 10:57:21PM +0200, Jakub Narebski wrote:
Errr... you are aware that you can use "git stash save <message>" (i.e.
specify commit message for stash; well, the subject), don't you?
I wasn't aware, but usually I like leaving more notes to myself than
just a single lines' worth of state. I should probably take another
look at "git stash" and see if it's a handy tool for me to use; but so
far I've been happy enough with "git checkout -b topic-name; git
commit".
- Ted