[OT] Git branch and merge


#1

I have been using Git for about a year now, but always in the master
branch. I decided to try working in a branch to get experience with
merging. Naturally enough, I am now observing some behaviour that I do
not understand. I would appreciate any explanation of what is happening
and whether this is expected behaviour or not.

I initially pull from the remote repository and then checkout -b
workcopy from the master. At this point workcopy and master are
identical. In workcopy I modify x.rb and y.rb. I then add/commit x.rb
in workcopy. Next I checkout back to master.

From what i had read about git I believed that all the modifications
that I made to x and y in workcopy only affectedi workcopy; and that
those files in the master branch were still pristine as when they had
been pulled. However, when I checkouted the master branch this is what
I saw:

$ git co master
M y.rb
Switched to branch master
$
$ git status

On branch master

Changed but not updated:

(use “git add …” to update what will be committed)

modified: y.rb

no changes added to commit (use “git add” and/or “git commit -a”)
$

A git diff on y.rb in both branches produced identical output. This
clearly indicates that the changes that I made in the working branch
affected the master branch too. This is something that I thought not
possible. Was I wrong in my belief or am I doing something wrong in my
implementation.

Further, I noted that x.rb had disappeared from view on the master even
though it had only been commited on the workcopy branch. However, when
I ran merge on the master then I saw this:

$ git merge workcopy
Updating bb48bcc…339ec9a
y.rb: needs update
Fast forward

…x.rb | 3 +
1 file changed, 3 insertions(+), 0 deletions(-)
$

I am somewhat confused by this behaviour. If what I do in a branch but
do not commit impacts the master while changes commited in the branch
simply disappear from view in the master then what is the advantage to
branching? What am I doing wrong?


#2

Well you didn’t commit y.rb. If you wanna save not commited changes for
later use you should use stash.

p.s. I’m sorry if this gets sent twice it wouldn’t let me submit because
the quote was too long. :slight_smile:


#3

2009/3/27 James B. removed_email_address@domain.invalid

those files in the master branch were still pristine as when they had

(use “git add …” to update what will be committed)

modified: y.rb

no changes added to commit (use “git add” and/or “git commit -a”)
$

This is because you had not committed the change to y.rb. A checkout
will
not overwrite modified (uncommitted) files. You should have seen a
message
when you switched to the master warning that y was modified (M
filename).
You will think this is the optimum behaviour the when you forget to
commit
before a switch.

A git diff on y.rb in both branches produced identical output. This
clearly indicates that the changes that I made in the working branch
affected the master branch too. This is something that I thought not
possible. Was I wrong in my belief or am I doing something wrong in my
implementation.

The master has not been affected, it is just the modified file left
there.

Further, I noted that x.rb had disappeared from view on the master even
though it had only been commited on the workcopy branch. However, when
I ran merge on the master then I saw this:

I do not understand how x.rb had disappeared from the master, you should
see
the original x.rb. If x.rb was a new file on the branch then you would
expect it to be missing from the master.

Colin


#4

James B. wrote:

I have been using Git for about a year now, but always in the master
branch. I decided to try working in a branch to get experience with
merging. Naturally enough, I am now observing some behaviour that I do
not understand. I would appreciate any explanation of what is happening
and whether this is expected behaviour or not.

I initially pull from the remote repository and then checkout -b
workcopy from the master. At this point workcopy and master are
identical. In workcopy I modify x.rb and y.rb. I then add/commit x.rb
in workcopy. Next I checkout back to master.

But you didn’t commit y.rb so the modifications still exist in your work
copy. (not your branch named workcopy, which would be very confusing to
me to name a branch that. I’d name it something like experimental or
after whatever feature I was working on).

From what i had read about git I believed that all the modifications
that I made to x and y in workcopy only affectedi workcopy; and that
those files in the master branch were still pristine as when they had
been pulled. However, when I checkouted the master branch this is what
I saw:

You misinterpreted what you read. The changes you make in a working copy
affect the working copy (i.e. the files you see when listing your
project files).

$ git co master
M y.rb
Switched to branch master
$
$ git status

On branch master

Changed but not updated:

(use “git add …” to update what will be committed)

modified: y.rb

no changes added to commit (use “git add” and/or “git commit -a”)
$

Of course y.rb in your working copy shows the modification because you
modified it. You didn’t commit it to your branch so git checkout of
master merges your working copy changes to what it gets from the master
branch effectively patching master’s version of the file with your
working copy changes. This is expected and good behavior. You wouldn’t
want git stomping on you local uncommitted changes.

I you have changes in your working copy when working on a branch and do
not want to commit those changes permanently, you can “stash” the
changes before checking out master. You do this using git stash command.
Typically, however, it makes sense to commit all your changes to the
branch before switch to another. After all, if it’s an experimental
branch and you’re at a reasonable time to switch away to something else
it’s okay to just commit everything whether it’s fully working or not.
It is an “experimental” branch after all.


#5

2009/3/27 James B. removed_email_address@domain.invalid

Please bear with me as I walk through this:

I start with a pull from the remote. I then create and checkout a
branch, say localtests. I modify a file X.rb on localtests. If I
switch back to the master via git checkout then the change to x.rb comes
with me into the master branch?

It is not ‘in’ the master branch as it has not been committed, it is
just in
your working copy, which is the master branch plus your modified file.
If you want to get rid of modified files (so your working copy is the
same
as the current branch or master) you can use:
git checkout .
Note the dot on the end. Be careful though, this will destroy any
uncommitted changes, do not get into the habit of doing it lightly or
you
will regret it at some point.

However, if I first commit the change
to x.rb on localtests then it does not?

If you commit it on the branch and switch to the master then the
modified
file is in the branch but the original is still in the master. You get
back
to the modified files by checking out the branch again.


#6

Please bear with me as I walk through this:

I start with a pull from the remote. I then create and checkout a
branch, say localtests. I modify a file X.rb on localtests. If I
switch back to the master via git checkout then the change to x.rb comes
with me into the master branch? However, if I first commit the change
to x.rb on localtests then it does not?


#7

I think that I may see where I went wrong. Regardless of which named
branch I am on, git automatically puts any changes that I make into what
is effectively an anonymous working copy branch, where they remain until
they are added to a branch’s future commit set. Is this correct?


#8

2009/3/27 James B. removed_email_address@domain.invalid

I think that I may see where I went wrong. Regardless of which named
branch I am on, git automatically puts any changes that I make into what
is effectively an anonymous working copy branch, where they remain until
they are added to a branch’s future commit set. Is this correct?

Not really, they are not on a branch, your working copy is just a set of
files in your folders. When you switch branches git overwrites them
with
the version from the repository for that branch, unless they have been
modified but not committed, in which case it does not overwrite them.
The git repository contains all the versions of all the files on all the
branches and when you checkout it copies the appropriate versions into
your
local folders (but not overwriting modified files as we have seen). A
commit copies files that you have modified and marked for commit into
the
repository (on the appropriate branch).

There are a number of good git tutorials on the web, google will find
them.
Perhaps looking at some of those would help to get the concepts sorted.
It
all seems a bit complex at first but once you have played with it for a
while you will wonder how life managed without it.


#9

Colin L. wrote:

There are a number of good git tutorials on the web, google will find
them. Perhaps looking at some of those would help to get the concepts sorted.
It all seems a bit complex at first but once you have played with it for a
while you will wonder how life managed without it.

As I wrote, I have been using git for about a year now. I converted all
our projects from Subversion last spring. And I have done quite a few
tutorials. I have no trouble in using git, I just now desire to see how
branch and merge works, without following a script so to speak.

When you switch branches git overwrites them with the version
from the repository for that branch, unless they have been
modified but not committed, in which case it does not overwrite
them. The git repository contains all the versions of all the files
on all the branches and when you checkout it copies the appropriate
versions into your local folders (but not overwriting modified files
as we have seen). A commit copies files that you have modified and
marked for commit into the repository (on the appropriate branch).

However, in addition to the forgoing, when I switched from a branch with
modified files into the master branch then git copied the modified files
into the master branch as well. This put the master branch into a state
as if I had edited those files in that branch. It was this behaviour
that confused me. I thought that whatever one did in a branch stayed in
that branch and did not follow one around modifying every other branch
that one enters.

How does one check for commits, and their contents, made to other
branches but not yet merged back into the master?


#10

Colin L. wrote:

Not really, they are not on a branch, your working copy is just a set of
files in your folders. When you switch branches git overwrites them
with
the version from the repository for that branch, unless they have been
modified but not committed, in which case it does not overwrite them.

I’m not sure what version of git you’re using, but I just did a sanity
check with a simple git repository. The version of git I’m using
(1.6.1.3) wouldn’t let me switch to another branch with local changes to
the working directory. I had to use git checkout --merge master, which
then performed a 3-way merge between the versions on the branch, master
and working. In this case the file did conflict, as it should have,
After using git mergetool to resolve the conflicts then I was able to
commit the merged file into the master branch.

Note that in this case both the branch and master had versions of the
file committed previously.


#11

2009/3/27 James B. removed_email_address@domain.invalid

As I wrote, I have been using git for about a year now. I converted all

as we have seen). A commit copies files that you have modified and
marked for commit into the repository (on the appropriate branch).

However, in addition to the forgoing, when I switched from a branch with
modified files into the master branch then git copied the modified files
into the master branch as well.

It is not copying the modified files anywhere, they are staying exactly
where they are, the working copy is always in the same place (unless
you
move the whole tree of folders of course).

This put the master branch into a state
as if I had edited those files in that branch. It was this behaviour
that confused me. I thought that whatever one did in a branch stayed in
that branch and did not follow one around modifying every other branch
that one enters.

Again, the branch is not being modified, a branch is only modified when
a
commit or similar is performed. It is the working copy that you are
talking
about.

How does one check for commits, and their contents, made to other
branches but not yet merged back into the master?

I Use gitk


#12

Robert W. wrote:

I’m not sure what version of git you’re using, but I just did a sanity
check with a simple git repository. The version of git I’m using
(1.6.1.3) wouldn’t let me switch to another branch with local changes to
the working directory.

I am stuck with Git 1.5.5 on CentOS-5.3. Unless and until some kind
soul adds a more recent version to EPEL.


#13

Colin L. wrote:

I am using 1.5.6.3 on ubuntu. I think the situation you are describing
may be because the file has been modified on the master and branch. I
think if you make a new branch, checkout the branch, modify a file
without committing (or staging) then checkout the master it will let
you do it and leave the file modified

This seems to be the case. I built and installed Git-1.6.2-1 and I get
the same behaviour as I observed with 1.5.5.

$ git pull

$ git co -b newbranch
$ echo junk > README
$ git status

On branch newbranch

Changed but not updated:

(use “git add …” to update what will be committed)

(use “git checkout – …” to discard changes in working

directory)

modified: README

no changes added to commit (use “git add” and/or “git commit -a”)
$
$ git co master
M README
Switched to branch “master”
[byrnejb@inet04 proforma.git]$ git status

On branch master

Changed but not updated:

(use “git add …” to update what will be committed)

(use “git checkout – …” to discard changes in working

directory)

modified: README

no changes added to commit (use “git add” and/or “git commit -a”)

I am still somewhat vague as to what is happening here but now at least
I know what to expect and that suffices.


#14

2009/3/27 Robert W. removed_email_address@domain.invalid

(1.6.1.3) wouldn’t let me switch to another branch with local changes to
the working directory. I had to use git checkout --merge master, which
then performed a 3-way merge between the versions on the branch, master
and working. In this case the file did conflict, as it should have,
After using git mergetool to resolve the conflicts then I was able to
commit the merged file into the master branch.

I am using 1.5.6.3 on ubuntu. I think the situation you are describing
may
be because the file has been modified on the master and branch. I think
if
you make a new branch, checkout the branch, modify a file without
committing
(or staging) then checkout the master it will let you do it and leave
the
file modified


#15

It might help to think of your SVN experience. In SVN when you checkout
a branch, you download a copy of the files in that branch in the repo.
When you commit, you upload your modified files to the branch in the
repository.

In Git, although you have your version of repository in a database on
your computer, the situation is similar. In Git, when you checkout a
branch Git loads the files in that branch from the repo to the working
directory, where they show in your file system and you can open them and
modify them. When you git commit them, the changes are written to the
repo.

In both Git & SVN, you generally make changes to your repository using
your vcs commands, and you make changes to the checked-out copy using
your editor. In both cases, branches exist in the repository, and the
files that you are working on have come from the repository. The
difference is that in Git the repo you are working from is your personal
version which is stored on your computer.