All of lore.kernel.org
 help / color / mirror / Atom feed
* More Beginning Git Questions
@ 2011-09-23 14:41 Jon Forrest
  2011-09-23 16:11 ` Matthieu Moy
                   ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Jon Forrest @ 2011-09-23 14:41 UTC (permalink / raw)
  To: git

I'm reading the git tutorial at
http://schacon.github.com/git/gittutorial.html
I'm a very literal reader so if something isn't clear
to me, I try to make the effort to understand it.

In reading about what happens when Alice pulls from Bob,
it says:

"Note that in general, Alice would want her local changes committed 
before initiating this "pull"."

This is an interesting statement. I'll come back to it shortly.

"If Bob’s work conflicts with what Alice did since their histories forked,"

Does this include both changes that Alice has checked in to
her repository and uncommitted changes in her working tree?

"Alice will use her working tree and the index to resolve conflicts,"

How does Alice use her working tree and index? Does this mean
she makes changes to her working tree so that the conflicts
no longer exist? How does the index play a part in this?
I thought that the index gets populated only when a
"git add" is done. Does Alice need to do "git add" as part
of the conflict resolution process?

"and existing local changes will interfere with the conflict resolution 
process"

Are "local changes" the changes in the working tree, the
uncommitted changes that Alice has added to her index, or
changes that Alice has committed to her local repository?

"(git will still perform the fetch but will refuse to merge
--- Alice will have to get rid of her local changes in
some way and pull again when this happens)."

Again, I'm not clear on which local changes this is talking
about. In other words, when the merge part of the pull is
done, what is examined locally? The first sentence about
Alice committing her local changes before pulling is what
got me thinking about all this.

I'm sorry if these are too pedantic.

Jon Forrest

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-23 14:41 More Beginning Git Questions Jon Forrest
@ 2011-09-23 16:11 ` Matthieu Moy
  2011-09-23 17:42 ` Jakub Narebski
  2011-09-23 18:47 ` Junio C Hamano
  2 siblings, 0 replies; 24+ messages in thread
From: Matthieu Moy @ 2011-09-23 16:11 UTC (permalink / raw)
  To: Jon Forrest; +Cc: git

Jon Forrest <nobozo@gmail.com> writes:

> "If Bob’s work conflicts with what Alice did since their histories forked,"
>
> Does this include both changes that Alice has checked in to
> her repository and uncommitted changes in her working tree?

Git will not allow you to do a "git pull" if your uncommited changes
touch the same files as the pull. So, you basically can't have conflicts
about uncommited changes with "git pull".

That's by design: solving conflicts can be hard, and you want the "last
commit" safety net while doing it. If you mess up your conflict
resolution, you can still "git reset --merge" and try again.

> "Alice will use her working tree and the index to resolve conflicts,"
>
> How does Alice use her working tree and index? Does this mean
> she makes changes to her working tree so that the conflicts
> no longer exist?

Yes.

> How does the index play a part in this?

Once the conflict is fixed in the working tree, you run "git add" to
mark the conflict as resolved.

And before this, the index contains half-merged versions of your file,
and "git diff" can show you the difference between them and your
worktree. See the user manual :

http://schacon.github.com/git/user-manual.html#resolving-a-merge

(BTW, that's not the official place for Git documentation, but since
kernel.org is down now ...)

> "and existing local changes will interfere with the conflict
> resolution process"

Probably this should have been "would have interfered" (and therefore
are forbidden by Git, as the following sentence says):

> "(git will still perform the fetch but will refuse to merge
> --- Alice will have to get rid of her local changes in
> some way and pull again when this happens)."

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-23 14:41 More Beginning Git Questions Jon Forrest
  2011-09-23 16:11 ` Matthieu Moy
@ 2011-09-23 17:42 ` Jakub Narebski
  2011-09-23 18:14   ` Jon Forrest
  2011-09-23 18:47 ` Junio C Hamano
  2 siblings, 1 reply; 24+ messages in thread
From: Jakub Narebski @ 2011-09-23 17:42 UTC (permalink / raw)
  To: Jon Forrest; +Cc: git

Jon Forrest <nobozo@gmail.com> writes:

> I'm reading the git tutorial at
> http://schacon.github.com/git/gittutorial.html

I recommend reading "Pro Git" book (http://progit.org)

> I'm a very literal reader so if something isn't clear
> to me, I try to make the effort to understand it.
> 
> In reading about what happens when Alice pulls from Bob,
> it says:
> 
> "Note that in general, Alice would want her local changes committed
> before initiating this "pull"."
> 
> This is an interesting statement. I'll come back to it shortly.
> 
> "If Bob’s work conflicts with what Alice did since their histories forked,"
> 
> Does this include both changes that Alice has checked in to
> her repository and uncommitted changes in her working tree?

Generally Alice shouldn't have uncommitted changes when doing
"git pull".

> "Alice will use her working tree and the index to resolve conflicts,"
> 
> How does Alice use her working tree and index? Does this mean
> she makes changes to her working tree so that the conflicts
> no longer exist? How does the index play a part in this?
> I thought that the index gets populated only when a
> "git add" is done. Does Alice need to do "git add" as part
> of the conflict resolution process?

This is actually a very important information.

When there is a merge conflicts, the index gets populated by more than
one version: "ours" (i.e. Alice version) in stage 2, "theirs"
(i.e. Bob version) in stage 3, and "base" (common ancestor version) in
stage 1.  The stage 0, where "git add" / "git stage" puts contents of
file, is empty.

You can see it using "git ls-files --abbrev --stage".
 
The working area gets populated with version that contains both "ours"
and "theirs" hunks using conflict markers (the 3-way textual merge,
like 'rcsmerge' or 'diff3 -E' does).  Sidenote: you can use "git
checkout --conflict=merge <file>" to re-create this version if you
messed up conflict resolution, or even --conflict=diff3 if you want
"base" (ancestor) version to be shown in conflict markers as
well... but this would discard your changes.

After resolving conflict you do "git add" on resolved file to mark it
as done.  This leaves you with only newly add-ed stage 0 in the index!

The pre-commit hook might check if you didn't accidentally marked as
resolved (added) file with [something that looks like] conflict
markers in it.

HTH
-- 
Jakub Narębski

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-23 17:42 ` Jakub Narebski
@ 2011-09-23 18:14   ` Jon Forrest
  2011-09-23 18:44     ` Mihamina Rakotomandimby
                       ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Jon Forrest @ 2011-09-23 18:14 UTC (permalink / raw)
  To: git

On 9/23/2011 10:42 AM, Jakub Narebski wrote:

> I recommend reading "Pro Git" book (http://progit.org)

I'm reading that too. I have some similar pedantic questions
about that book but I don't want to be a pest so I'll
stick with the tutorial now. Maybe some of my questions
about "Pro Git" will get answered.

>> Does this include both changes that Alice has checked in to
>> her repository and uncommitted changes in her working tree?
>
> Generally Alice shouldn't have uncommitted changes when doing
> "git pull".

That's what the tutorial said but I'm trying to understand
what happens if she does have uncommitted changes. I'm
trying to understand the total picture.

> When there is a merge conflicts, the index gets populated by more than
> one version: "ours" (i.e. Alice version) in stage 2, "theirs"
> (i.e. Bob version) in stage 3, and "base" (common ancestor version) in
> stage 1.  The stage 0, where "git add" / "git stage" puts contents of
> file, is empty.

I didn't know there were multiple staging areas.

> You can see it using "git ls-files --abbrev --stage".

That's very helpful.

Thanks to (almost) everyone who has responded. I'm hoping that
others new to Git will benefit from this discussion.

Jon

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-23 18:14   ` Jon Forrest
@ 2011-09-23 18:44     ` Mihamina Rakotomandimby
  2011-09-23 18:59     ` Jakub Narebski
  2011-09-24 20:22     ` tactical
  2 siblings, 0 replies; 24+ messages in thread
From: Mihamina Rakotomandimby @ 2011-09-23 18:44 UTC (permalink / raw)
  To: Jon Forrest; +Cc: git

On 09/23/2011 09:14 PM, Jon Forrest wrote:
>
> Thanks to (almost) everyone who has responded. I'm hoping that
> others new to Git will benefit from this discussion.

It does, it does...
I'm working on an internal parallel documentation on using Hg and Git 
and this conflict resolution topic is... important.

-- 
RMA.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-23 14:41 More Beginning Git Questions Jon Forrest
  2011-09-23 16:11 ` Matthieu Moy
  2011-09-23 17:42 ` Jakub Narebski
@ 2011-09-23 18:47 ` Junio C Hamano
  2 siblings, 0 replies; 24+ messages in thread
From: Junio C Hamano @ 2011-09-23 18:47 UTC (permalink / raw)
  To: Jon Forrest; +Cc: git

Jon Forrest <nobozo@gmail.com> writes:

> "Note that in general, Alice would want her local changes committed
> before initiating this "pull"."
>
> This is an interesting statement. I'll come back to it shortly.
>
> "If Bob’s work conflicts with what Alice did since their histories forked,"
>
> Does this include both changes that Alice has checked in to her
> repository and uncommitted changes in her working tree?

We do not consider uncommitted changes part of _any_ history. You can
think of them as floating on top of the history of the branch that is
currently checked out [*1*].

> "Alice will use her working tree and the index to resolve conflicts,"
>
> How does Alice use her working tree and index? Does this mean
> she makes changes to her working tree so that the conflicts
> no longer exist? How does the index play a part in this?
>
> I thought that the index gets populated only when a
> "git add" is done. Does Alice need to do "git add" as part
> of the conflict resolution process?

If you start from a clean working tree (i.e. no local changes), then after
any "mergy" operation (not just "git pull" and "git merge" but things like
"cherry-pick", "checkout -m", "rebase" and "am -3" that can stop due to
conflicts), one of the three things will happen to each of the paths in
the project:

 1. If the result of the operation can be mechanically known, and if that
    is the same as your current state (i.e. HEAD or "ours"), nothing
    happens.

 2. If the result of the operation can be mechanically known, and if that
    is different from your current state (i.e. HEAD or "ours"), the index
    entry for that path records the result, and the path in the working
    tree is updated to match that result.

 3. If the result of the operation cannot be mechanically known
    (i.e. merge conflict), the index entry for that path will record up to
    3 "stages", stage #1 representing the contents the conflicting sides
    diverged from (i.e. common ancestor), stage #2 representing the
    contents of your current state (i.e. HEAD or "ours") and stage #3
    representing the contents of the other branch (i.e. MERGE_HEAD or
    "theirs"), and the path in the working tree is updated to represent it
    with conflict markers.

You conclude the "mergy" operation by resolving conflicts in the working
tree for paths in the category 3, tell Git that you are done with these
paths using "git add $path" (but paths in no other categories!!!).
Because cleanly merged paths are already updated in the index (see
2. above), that is all needed to bring the index to the state that
represents the desired result of the "mergy" operation.

Even if you have local changes in your working tree, as long as your index
exactly matches HEAD when you start your "mergy" operation, thanks to the
rule for "result matches the current HEAD" case (see 1. above), the result
of your "mergy" operation recorded by the procedure in the previous
paragraph will not be contaminated with your local changes.

The precondition for all of the above to work is that you start from a
clean index, and that is why "git merge" refuses to start if your index
already has changes relative to HEAD.

Also, for cases 2. and 3., updating the files in the working tree to match
the auto-merge result (case 2.) or to show the conflicted state (case 3.)
requires Git to overwrite the file, which is bad if you have local changes
to the files in the working tree. To prevent lossage, "mergy" operations
will notice if paths in categories 2. and 3. have local changes in the
working tree, and refuses to work if that is the case.


[Footnote]

*1* This incidentally is important to have in your mental model to
understand how to use "git checkout $branch" to switch branches.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-23 18:14   ` Jon Forrest
  2011-09-23 18:44     ` Mihamina Rakotomandimby
@ 2011-09-23 18:59     ` Jakub Narebski
  2011-09-24 20:22     ` tactical
  2 siblings, 0 replies; 24+ messages in thread
From: Jakub Narebski @ 2011-09-23 18:59 UTC (permalink / raw)
  To: Jon Forrest; +Cc: git

BTW it is customary on git mailing list to send reply not only to git
mailing list, but also to all responders (to previous author, cc to
list and to others).

Jon Forrest <nobozo@gmail.com> writes:
> On 9/23/2011 10:42 AM, Jakub Narebski wrote:
>> Jon Forrest <nobozo@gmail.com> writes:
 
>>> Does this include both changes that Alice has checked in to
>>> her repository and uncommitted changes in her working tree?
>>
>> Generally Alice shouldn't have uncommitted changes when doing
>> "git pull".
> 
> That's what the tutorial said but I'm trying to understand
> what happens if she does have uncommitted changes. I'm
> trying to understand the total picture.

If Alice have uncommitted changes, in working tree and/or in the
index, what git does is try to merge if possible; if conflict or new
versions from "theirs" touch changed file, git refuses to do a merge.
 
The idea is to do merge if possible, but abort if there is any chance
that user's changes would be lost.

>> When there is a merge conflicts, the index gets populated by more than
>> one version: "ours" (i.e. Alice version) in stage 2, "theirs"
>> (i.e. Bob version) in stage 3, and "base" (common ancestor version) in
>> stage 1.  The stage 0, where "git add" / "git stage" puts contents of
>> file, is empty.
> 
> I didn't know there were multiple staging areas.

Those are called "stages" inside one single staging area (the index).
 
>> You can see it using "git ls-files --abbrev --stage".
> 
> That's very helpful.

Also in the case of conflict, "git diff" would show combined diff of
changes.

Try both on some example.

-- 
Jakub Narębski

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-23 18:14   ` Jon Forrest
  2011-09-23 18:44     ` Mihamina Rakotomandimby
  2011-09-23 18:59     ` Jakub Narebski
@ 2011-09-24 20:22     ` tactical
  2011-09-24 20:53       ` Frans Klaver
  2011-09-24 21:10       ` Jakub Narebski
  2 siblings, 2 replies; 24+ messages in thread
From: tactical @ 2011-09-24 20:22 UTC (permalink / raw)
  To: git

Jon Forrest wrote:

>> Generally Alice shouldn't have uncommitted changes when doing
>> "git pull".
> 
> That's what the tutorial said but I'm trying to understand
> what happens if she does have uncommitted changes. I'm
> trying to understand the total picture.

Mercurial allows this, and it's a very powerful feature.  After reading 
this thread, I could not believe Git didn't pulling with local changes, and 
so I tried it, and also asked on IRC -- and it seems that Git really 
doesn't.

If this is an important part of your workflow (as it is mine), I'd 
recommend using Mercurial if possible.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-24 20:22     ` tactical
@ 2011-09-24 20:53       ` Frans Klaver
  2011-09-24 22:17         ` tactical
  2011-09-24 21:10       ` Jakub Narebski
  1 sibling, 1 reply; 24+ messages in thread
From: Frans Klaver @ 2011-09-24 20:53 UTC (permalink / raw)
  To: git

On Sat, 24 Sep 2011 22:22:31 +0200, tactical <a5158017@nepwk.com> wrote:

> Mercurial allows this, and it's a very powerful feature.  After reading
> this thread, I could not believe Git didn't pulling with local changes,  
> and so I tried it, and also asked on IRC -- and it seems that Git really
> doesn't.

Git doesn't do it implicitly. Be explicit about it

$ git stash
$ git pull
$ git stash pop

seems to do exactly what you want.

Cheers,
Frans

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-24 20:22     ` tactical
  2011-09-24 20:53       ` Frans Klaver
@ 2011-09-24 21:10       ` Jakub Narebski
  2011-09-24 22:10         ` tactical
  1 sibling, 1 reply; 24+ messages in thread
From: Jakub Narebski @ 2011-09-24 21:10 UTC (permalink / raw)
  To: tactical; +Cc: git

tactical <a5158017@nepwk.com> writes:
> Jon Forrest wrote:
> > Jakub Narebski wrote:
 
> > > Generally Alice shouldn't have uncommitted changes when doing
> > > "git pull".
> > 
> > That's what the tutorial said but I'm trying to understand
> > what happens if she does have uncommitted changes. I'm
> > trying to understand the total picture.
> 
> Mercurial allows this, and it's a very powerful feature.

You *do* realize thet "hg pull" is "git fetch", don't you?

>  After reading 
> this thread, I could not believe Git didn't pulling with local changes, and 
> so I tried it, and also asked on IRC -- and it seems that Git really 
> doesn't.
> 
> If this is an important part of your workflow (as it is mine), I'd 
> recommend using Mercurial if possible.
> 

So the question is if mercurial allows _merging_ with local
changes... and from the thread it looks like git dies allow it, as
long as changes are isolated from changes brought by merge.

Anyway merging with local changes is an easy way to f**k up your
changes in unrecoverable way, IMVHO...

-- 
Jakub Narębski

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-24 21:10       ` Jakub Narebski
@ 2011-09-24 22:10         ` tactical
  2011-09-25 13:24           ` Jakub Narebski
  0 siblings, 1 reply; 24+ messages in thread
From: tactical @ 2011-09-24 22:10 UTC (permalink / raw)
  To: git

Jakub Narebski wrote:

>>> > Generally Alice shouldn't have uncommitted changes when doing
>>> > "git pull".
>>> 
>>> That's what the tutorial said but I'm trying to understand
>>> what happens if she does have uncommitted changes. I'm
>>> trying to understand the total picture.
>> 
>> Mercurial allows this, and it's a very powerful feature.
> 
> You *do* realize thet "hg pull" is "git fetch", don't you?

Yes.  This is what I mean:

    c:\test>hg diff

    diff --git a/foo b/foo
    --- a/foo
    +++ b/foo
    @@ -1,1 +1,2 @@
     test
    +new line

    c:\test>hg incoming --patch clone

    comparing with clone
    searching for changes
    changeset:   1:0a897c3462a8
    tag:         tip
    user:        tactical
    date:        Sat Sep 24 23:03:21 2011 +0100
    summary:     bar

    diff --git a/foo b/foo
    --- a/foo
    +++ b/foo
    @@ -1,1 +1,2 @@
     test
    +bar

    c:\test>hg pull clone

    pulling from clone
    searching for changes
    adding changesets
    adding manifests
    adding file changes
    added 1 changesets with 1 changes to 1 files
    (run 'hg update' to get a working copy)

    c:\test>hg update

    merging foo

Now KDiff3 automagically appears (because of the line conflict).

>>  After reading 
>> this thread, I could not believe Git didn't pulling with local changes, and 
>> so I tried it, and also asked on IRC -- and it seems that Git really 
>> doesn't.
>> 
>> If this is an important part of your workflow (as it is mine), I'd 
>> recommend using Mercurial if possible.
>> 
> 
> So the question is if mercurial allows _merging_ with local
> changes... and from the thread it looks like git dies allow it, as
> long as changes are isolated from changes brought by merge.

For that reason, Git doesn't support my workflow at all.

> Anyway merging with local changes is an easy way to f**k up your
> changes in unrecoverable way, IMVHO...

Mercurial backs everything up before doing this merge, so if I do lose my
local changes, I can start over with this:

    hg resolve --unmark --all
    hg resolve --all

Now KDiff3 comes up again, with the same data as before.  No data lost.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-24 20:53       ` Frans Klaver
@ 2011-09-24 22:17         ` tactical
  2011-09-24 22:59           ` Seth Robertson
  0 siblings, 1 reply; 24+ messages in thread
From: tactical @ 2011-09-24 22:17 UTC (permalink / raw)
  To: git

Frans Klaver wrote:

>> Mercurial allows this, and it's a very powerful feature.  After reading
>> this thread, I could not believe Git didn't pulling with local changes,  
>> and so I tried it, and also asked on IRC -- and it seems that Git really
>> doesn't.
> 
> Git doesn't do it implicitly. Be explicit about it
> 
> $ git stash
> $ git pull
> $ git stash pop
> 
> seems to do exactly what you want.

Does popping the stash allow for a three-way merge?  If not, this doesn't
really solve the problem.

Thanks

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-24 22:17         ` tactical
@ 2011-09-24 22:59           ` Seth Robertson
  2011-09-25  2:16             ` tactical
  0 siblings, 1 reply; 24+ messages in thread
From: Seth Robertson @ 2011-09-24 22:59 UTC (permalink / raw)
  To: tactical; +Cc: git


In message <1m2c90ds9e46c.7agk88pbgjl8$.dlg@40tude.net>, tactical writes:

    Frans Klaver wrote:

    >> Mercurial allows this, and it's a very powerful feature.  After reading
    >> this thread, I could not believe Git didn't pulling with local changes,
    >> and so I tried it, and also asked on IRC -- and it seems that Git really
    >> doesn't.
    >
    > Git doesn't do it implicitly. Be explicit about it
    >
    > $ git stash
    > $ git pull
    > $ git stash pop
    >
    > seems to do exactly what you want.

    Does popping the stash allow for a three-way merge?  If not, this doesn't
    really solve the problem.

As I explained on IRC, you can use the following workflow to create a
three way merge.

git stash
git fetch
git merge @{u} stash
git mergetool
git stash drop

You can then do whatever other work you want.  You can repeat this
workflow as often as you want.  When you are done, then you can
commit:

git commit -a -m "My important work"

This is of course easily scriptable so it becomes one command to you.
And since you mentioned it, if the merge went poorly and you wanted to
start over (only before you dropped the stash of course), you can:

git reset --hard HEAD
git merge @{u} stash

And then continue with the rest of the workflow above.


Of course, I would recommend you consider some of the more gitish
workflows.  Commit early and often.  `git pull --rebase` as often as
you want, and then use `git rebase -i @{u}^` to squash all of your
in-progress commits together.  With appropriate in-progress commit
message crafting, you can use the --autosquash functionality of
git-rebase to make this process easier.

					-Seth Robertson

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-24 22:59           ` Seth Robertson
@ 2011-09-25  2:16             ` tactical
  2011-09-25 13:22               ` Jakub Narebski
  0 siblings, 1 reply; 24+ messages in thread
From: tactical @ 2011-09-25  2:16 UTC (permalink / raw)
  To: git

Seth Robertson wrote:

> As I explained on IRC, you can use the following workflow to create a
> three way merge.
> 
> git stash
> git fetch
> git merge @{u} stash
> git mergetool
> git stash drop
> 
> You can then do whatever other work you want.  You can repeat this
> workflow as often as you want.  When you are done, then you can
> commit:
> 
> git commit -a -m "My important work"
> 
> This is of course easily scriptable so it becomes one command to you.
> And since you mentioned it, if the merge went poorly and you wanted to
> start over (only before you dropped the stash of course), you can:
> 
> git reset --hard HEAD
> git merge @{u} stash

Thanks.  It's a shame, however, that Git makes the user jump through hoops
to achieve such a simple thing.

> Of course, I would recommend you consider some of the more gitish
> workflows.

And that, I feel, is a problem with Git.  In some cases, you can't do
things how you want -- you have to do things how Git wants.

Another example of this is the lack of support for anonymous branching as
part of a normal workflow in Git.  Anonymous branching is very powerful and
very simple.  I use it all the time in Mercurial.

> Commit early and often.  `git pull --rebase` as often as
> you want, and then use `git rebase -i @{u}^` to squash all of your
> in-progress commits together.  With appropriate in-progress commit
> message crafting, you can use the --autosquash functionality of
> git-rebase to make this process easier.

Thanks for the ideas, but they don't solve my particular problem.  The
reason I regularly pull with local changes is that I like to use clones for
short-term branching (because it's powerful and flexible -- for example,
when I create my "TryFeatureX" clone, I have two versions of my project on
disk, and I can run them side by side).

In order to avoid pointless merges, I sometimes don't commit until I've
pulled.  Sure, I could commit and then rebase instead, but, in this
situation, rebasing is effectively merging and committing in one step.
With my workflow, however, after I merge, I can still make changes (and do
other stuff like running unit tests) before finally committing.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-25  2:16             ` tactical
@ 2011-09-25 13:22               ` Jakub Narebski
  2011-09-25 20:23                 ` tactical
  0 siblings, 1 reply; 24+ messages in thread
From: Jakub Narebski @ 2011-09-25 13:22 UTC (permalink / raw)
  To: tactical; +Cc: git

tactical <a5158017@nepwk.com> writes:
> Seth Robertson wrote:
> 
> > As I explained on IRC, you can use the following workflow to create a
> > three way merge.
> > 
> > git stash
> > git fetch
> > git merge @{u} stash
> > git mergetool
> > git stash drop
> > 
> > You can then do whatever other work you want.  You can repeat this
> > workflow as often as you want.  When you are done, then you can
> > commit:
> > 
> > git commit -a -m "My important work"
> > 
> > This is of course easily scriptable so it becomes one command to you.
> > And since you mentioned it, if the merge went poorly and you wanted to
> > start over (only before you dropped the stash of course), you can:
> > 
> > git reset --hard HEAD
> > git merge @{u} stash
> 
> Thanks.  It's a shame, however, that Git makes the user jump through hoops
> to achieve such a simple thing.

A short time after "git stash" was added to Git there was proposal to
automatically use git stash to allow merging with "dirty tree",
i.e. with uncomitted changes.  This idea was abandoned, if I remember
it correctly because a.) there were too many corner-cases b.) it
wasn't necessary in most cases.
 
With merging into branch with uncomitted changes your fairly well
understood 3-way merge (sometimes virtual 3-way merge in the case of
multiple common ancestors) would turn into 4-way merge.  Even if you
can automate it somehow (I do wonder how Mercurial manages that),
there could be problem resolving conflicts, unless you happen to touch
different parts of file.

> > Of course, I would recommend you consider some of the more gitish
> > workflows.
> 
> And that, I feel, is a problem with Git.  In some cases, you can't do
> things how you want -- you have to do things how Git wants.

Please take into account the fact that when you were creating your
workflow to suit your situation you were "forced" to fit it to
Mercurial abilities and best practices.  No wonder that it does not
fit Git-ish workflows.

What you use uncomitted changes for, I would use is a separate branch,
and keep it rebasing (something like using 'mq' in Mercurial).
 
> Another example of this is the lack of support for anonymous branching as
> part of a normal workflow in Git.  Anonymous branching is very powerful and
> very simple.  I use it all the time in Mercurial.

What do you use anonymous branching for?

Note that with Git by default pushing "matching" branches, you can
create private local-only branches.  The have to have _some_ name
(even if it is 'foo/temp'), but I think that it makes them perhaps
more work to create, but easier to use (to switch branches)... and for
single anonymous branch you can always use "detached HEAD".
 
-- 
Jakub Narębski

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-24 22:10         ` tactical
@ 2011-09-25 13:24           ` Jakub Narebski
  0 siblings, 0 replies; 24+ messages in thread
From: Jakub Narebski @ 2011-09-25 13:24 UTC (permalink / raw)
  To: tactical; +Cc: git

tactical <a5158017@nepwk.com> writes:
> Jakub Narebski wrote:

> > Anyway merging with local changes is an easy way to f**k up your
> > changes in unrecoverable way, IMVHO...
> 
> Mercurial backs everything up before doing this merge, so if I do lose my
> local changes, I can start over with this:
> 
>     hg resolve --unmark --all
>     hg resolve --all

Well, that's the advantage of database-like transaction based atomic
operations.

OTOH reflog allows to back out not only last operation...

-- 
Jakub Narębski

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-25 13:22               ` Jakub Narebski
@ 2011-09-25 20:23                 ` tactical
  2011-09-25 20:58                   ` Jakub Narebski
  0 siblings, 1 reply; 24+ messages in thread
From: tactical @ 2011-09-25 20:23 UTC (permalink / raw)
  To: git

Jakub Narebski wrote:

> With merging into branch with uncomitted changes your fairly well
> understood 3-way merge (sometimes virtual 3-way merge in the case of
> multiple common ancestors) would turn into 4-way merge.

I don't see why it would be a four-way merge rather than a three-way merge.

> Even if you
> can automate it somehow (I do wonder how Mercurial manages that),
> there could be problem resolving conflicts, unless you happen to touch
> different parts of file.

This behaviour is by design in Mercurial.  It's simple, and it works.  I've
never had a problem with resolving conflicts here, and I don't see why I
ever would.

>> And that, I feel, is a problem with Git.  In some cases, you can't do
>> things how you want -- you have to do things how Git wants.
> 
> Please take into account the fact that when you were creating your
> workflow to suit your situation you were "forced" to fit it to
> Mercurial abilities and best practices.  No wonder that it does not
> fit Git-ish workflows.

No, I came to the distributed world only recently, from Subversion.  I
choose to use clones over plain anonymous branching, over bookmarks, and
over named branching because I prefer the approach.  I can, of course, do
"Git branching" in Mercurial very easily if I want (with Mercurial
bookmarks).

> What you use uncomitted changes for, I would use is a separate branch,
> and keep it rebasing (something like using 'mq' in Mercurial).

Yes, but, as I mentioned, rebasing is less flexible.  A rebase here is
effectively a merge and a commit in one step, whereas my approach separates
the merge and the commit.

>> Another example of this is the lack of support for anonymous branching as
>> part of a normal workflow in Git.  Anonymous branching is very powerful and
>> very simple.  I use it all the time in Mercurial.
> 
> What do you use anonymous branching for?

Anonymous branching is great for minor divergence that isn't really
significant enough to deserve a name.  It's also great for branches that
*are* significant enough to deserve a name, but where you want to defer
naming the branch right up until you merge it into another branch.  At that
point you can 'name' the branch in the commit message.  (Of course, you
could also create a Mercurial bookmark at that point, and then you'd
essentially have a "Git branch".)

> Note that with Git by default pushing "matching" branches, you can
> create private local-only branches.  The have to have _some_ name
> (even if it is 'foo/temp'), but I think that it makes them perhaps
> more work to create, but easier to use (to switch branches)... and for
> single anonymous branch you can always use "detached HEAD".

>From what I read, detached heads are subject to garbage collection.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-25 20:23                 ` tactical
@ 2011-09-25 20:58                   ` Jakub Narebski
  2011-09-25 21:07                     ` tactical
  0 siblings, 1 reply; 24+ messages in thread
From: Jakub Narebski @ 2011-09-25 20:58 UTC (permalink / raw)
  To: tactical; +Cc: git

tactical <a5158017@nepwk.com> writes:
> Jakub Narebski wrote:
> 
> > With merging into branch with uncomitted changes your fairly well
> > understood 3-way merge (sometimes virtual 3-way merge in the case of
> > multiple common ancestors) would turn into 4-way merge.
> 
> I don't see why it would be a four-way merge rather than a three-way merge.

You have four version: "base" (ancestor version), "theirs"
(branch/clone being merged), "ours" (comitted changes on current
branch) and "new" (uncomitted changes on current branch).

Unless Mercurial does 3-way merge of "new", "theirs" and "base"...
with transaction based atomicity (saving "new" before attempting
merge) they can do that.

With Git you have additional complication: the index state.

> > Even if you
> > can automate it somehow (I do wonder how Mercurial manages that),
> > there could be problem resolving conflicts, unless you happen to touch
> > different parts of file.
> 
> This behaviour is by design in Mercurial.  It's simple, and it works.  I've
> never had a problem with resolving conflicts here, and I don't see why I
> ever would.

It if really is 3-way merge, you wouldn't.  If it isn't (e.g. it is
3-way merge + applying patch, like merge + stash apply in git), then
there are [nasty] corner cases.
 
Anyway I hope that Mercurial does test this feature extensively.

[...]
> > What you use uncomitted changes for, I would use is a separate branch,
> > and keep it rebasing (something like using 'mq' in Mercurial).
> 
> Yes, but, as I mentioned, rebasing is less flexible.  A rebase here is
> effectively a merge and a commit in one step, whereas my approach separates
> the merge and the commit.

Errr... what?  You first commit your changes, then keep it rebasing to
keep them up to date on top of fresh version.
 
> > > Another example of this is the lack of support for anonymous branching as
> > > part of a normal workflow in Git.  Anonymous branching is very powerful and
> > > very simple.  I use it all the time in Mercurial.
> > 
> > What do you use anonymous branching for?
> 
> Anonymous branching is great for minor divergence that isn't really
> significant enough to deserve a name.  It's also great for branches that
> *are* significant enough to deserve a name, but where you want to defer
> naming the branch right up until you merge it into another branch.  At that
> point you can 'name' the branch in the commit message.

I think you can use detached HEAD for that, at least when working on
one issue at a time (you have to name branch when switching to some
other work).

> (Of course, you
> could also create a Mercurial bookmark at that point, and then you'd
> essentially have a "Git branch".)

Except for the fact that AFAIK Mercurial bookmarks have single global
namespace for branch (bookmark) names, while Git uses more flexible
but less newbie-user-friendly branch to remote-tracking branch name
mapping via "refspec".
 
> > Note that with Git by default pushing "matching" branches, you can
> > create private local-only branches.  The have to have _some_ name
> > (even if it is 'foo/temp'), but I think that it makes them perhaps
> > more work to create, but easier to use (to switch branches)... and for
> > single anonymous branch you can always use "detached HEAD".
> 
> From what I read, detached heads are subject to garbage collection.
 
No, HEAD is protected against garbage collecting.  To be sure you
should name a branch when switching branches, though reflog would
protect you for 30 days (by default) even if you don't do that.

-- 
Jakub Narębski

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-25 20:58                   ` Jakub Narebski
@ 2011-09-25 21:07                     ` tactical
  2011-09-26  0:34                       ` Konstantin Khomoutov
  0 siblings, 1 reply; 24+ messages in thread
From: tactical @ 2011-09-25 21:07 UTC (permalink / raw)
  To: git

Jakub Narebski wrote:

>>> With merging into branch with uncomitted changes your fairly well
>>> understood 3-way merge (sometimes virtual 3-way merge in the case of
>>> multiple common ancestors) would turn into 4-way merge.
>> 
>> I don't see why it would be a four-way merge rather than a three-way merge.
> 
> You have four version: "base" (ancestor version), "theirs"
> (branch/clone being merged), "ours" (comitted changes on current
> branch) and "new" (uncomitted changes on current branch).
> 
> Unless Mercurial does 3-way merge of "new", "theirs" and "base"...
> with transaction based atomicity (saving "new" before attempting
> merge) they can do that.

I've not read the code, but surely Mercurial does a three-way merge here.
It wouldn't be sane to do anything else.

>>> What you use uncomitted changes for, I would use is a separate branch,
>>> and keep it rebasing (something like using 'mq' in Mercurial).
>> 
>> Yes, but, as I mentioned, rebasing is less flexible.  A rebase here is
>> effectively a merge and a commit in one step, whereas my approach separates
>> the merge and the commit.
> 
> Errr... what?  You first commit your changes, then keep it rebasing to
> keep them up to date on top of fresh version.

Like I said before, with my approach, after I merge, I can check that
everything still compiles, that unit tests still pass, and so on, before
finally checking in.  Rebasing, on the other hand, is essentially merging
and checking in in one step.  *After* you've rebased, you can run unit
tests, etc., but you've *already* checked in at that point.  (Sure, you
could then mutate history if need be, but it's rather less flexible than my
approach, where the check-in is not made until desired.)

>>> What do you use anonymous branching for?
>> 
>> Anonymous branching is great for minor divergence that isn't really
>> significant enough to deserve a name.  It's also great for branches that
>> *are* significant enough to deserve a name, but where you want to defer
>> naming the branch right up until you merge it into another branch.  At that
>> point you can 'name' the branch in the commit message.
> 
> I think you can use detached HEAD for that, at least when working on
> one issue at a time (you have to name branch when switching to some
> other work).

But in Mercurial I can switch between anonymous branches as much as I like
without anything ever being deleted.

>> From what I read, detached heads are subject to garbage collection.
>  
> No, HEAD is protected against garbage collecting.  To be sure you
> should name a branch when switching branches, though reflog would
> protect you for 30 days (by default) even if you don't do that.

So Git doesn't really support anonymous branching as part of a normal
workflow.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-25 21:07                     ` tactical
@ 2011-09-26  0:34                       ` Konstantin Khomoutov
  2011-09-26  0:56                         ` tactical
  0 siblings, 1 reply; 24+ messages in thread
From: Konstantin Khomoutov @ 2011-09-26  0:34 UTC (permalink / raw)
  To: tactical; +Cc: git

On Sun, Sep 25, 2011 at 10:07:24PM +0100, tactical wrote:

[...]
> > I think you can use detached HEAD for that, at least when working on
> > one issue at a time (you have to name branch when switching to some
> > other work).
> 
> But in Mercurial I can switch between anonymous branches as much as I like
> without anything ever being deleted.
> 
> >> From what I read, detached heads are subject to garbage collection.
> >  
> > No, HEAD is protected against garbage collecting.  To be sure you
> > should name a branch when switching branches, though reflog would
> > protect you for 30 days (by default) even if you don't do that.
> 
> So Git doesn't really support anonymous branching as part of a normal
> workflow.

I perceive a certain logical fallacy here: you cannot switch between
anything anonymous because to switch, you should somehow identify
something to switch to--a name in whatever sense we put into this word.
As I understand, by switching between branches in Mercurial you mean
switching between directories with clones; if so, you had had to name
those directories when they were created.

As to branches, they do have names in Git but they are very loosely
coupled with their names: tag a tip of some branch (to still have a
handle on that tip commit) then delete that branch--there will be no
traces of that branch's name left, the branch's name is not encoded in
its history in any way.  The branch names is just a way to not mess with
SHA-1 names of commits (and to have references to those commits to keep
them out of consideration for garbage collection).
Hence the idea to demand support for anonymous branches in Git's model
is just unfounded.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-26  0:34                       ` Konstantin Khomoutov
@ 2011-09-26  0:56                         ` tactical
  2011-09-26  1:34                           ` Andrew Ardill
  2011-09-26 18:03                           ` Jakub Narebski
  0 siblings, 2 replies; 24+ messages in thread
From: tactical @ 2011-09-26  0:56 UTC (permalink / raw)
  To: git

Konstantin Khomoutov wrote:

>>>> From what I read, detached heads are subject to garbage collection.
>>>  
>>> No, HEAD is protected against garbage collecting.  To be sure you
>>> should name a branch when switching branches, though reflog would
>>> protect you for 30 days (by default) even if you don't do that.
>> 
>> So Git doesn't really support anonymous branching as part of a normal
>> workflow.
> 
> I perceive a certain logical fallacy here: you cannot switch between
> anything anonymous because to switch, you should somehow identify
> something to switch to--a name in whatever sense we put into this word.

In Mercurial, you can just update to a particular changeset (and you
identify that changeset by repository-local revision number or globally
unique ID) and then commit again.  The point is that there's no need to
give a label to a head in Mercurial (although you can if you want to, using
Mercurial bookmarks, which are basically the same as what Git uses).

Here's an example of anonymous branching:

    c:\test>hg init

    c:\test>echo test>foo

    c:\test>hg commit --addremove -m initial
    adding foo

    c:\test>echo first>>foo

    c:\test>hg commit -m first

    c:\test>hg log
    changeset:   1:3e895ec28d6c
    tag:         tip
    user:        tactical
    date:        Mon Sep 26 01:39:46 2011 +0100
    summary:     first

    changeset:   0:b51644bb3450
    user:        tactical
    date:        Mon Sep 26 01:39:40 2011 +0100
    summary:     initial

    c:\test>hg update 0
    1 files updated, 0 files merged, 0 files removed, 0 files unresolved

    c:\test>echo second>>foo

    c:\test>hg commit -m second
    created new head

    c:\test>hg glog
    @  changeset:   2:35c82a7e7de1
    |  tag:         tip
    |  parent:      0:b51644bb3450
    |  user:        tactical
    |  date:        Mon Sep 26 01:40:10 2011 +0100
    |  summary:     second
    |
    | o  changeset:   1:3e895ec28d6c
    |/   user:        tactical
    |    date:        Mon Sep 26 01:39:46 2011 +0100
    |    summary:     first
    |
    o  changeset:   0:b51644bb3450
       user:        tactical
       date:        Mon Sep 26 01:39:40 2011 +0100
       summary:     initial

I now have two anonymous branches, and these will never be garbage
collected.  I can easily update to either branch with "hg update 1" or "hg
update 2" (or "hg update 0" again, if i want to create yet another
anonymous branch).

> As I understand, by switching between branches in Mercurial you mean
> switching between directories with clones;

No.  Clones are a different topic.

> As to branches, they do have names in Git but they are very loosely
> coupled with their names: tag a tip of some branch (to still have a
> handle on that tip commit) then delete that branch--there will be no
> traces of that branch's name left, the branch's name is not encoded in
> its history in any way.

Git branch names are basically the same as Mercurial bookmarks.  The
difference is that in Mercurial you don't *have* to use bookmarks.

> The branch names is just a way to not mess with
> SHA-1 names of commits (and to have references to those commits to keep
> them out of consideration for garbage collection).
> Hence the idea to demand support for anonymous branches in Git's model
> is just unfounded.

I think it's simply a weakness of Git.  There are zero problems with
anonymous branching in Mercurial, and it's a very powerful and simple
system.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-26  0:56                         ` tactical
@ 2011-09-26  1:34                           ` Andrew Ardill
  2011-09-26  1:42                             ` tactical
  2011-09-26 18:03                           ` Jakub Narebski
  1 sibling, 1 reply; 24+ messages in thread
From: Andrew Ardill @ 2011-09-26  1:34 UTC (permalink / raw)
  To: tactical; +Cc: git

On 26 September 2011 10:56, tactical <a5158017@nepwk.com> wrote:
> Konstantin Khomoutov wrote:
>
>>>>> From what I read, detached heads are subject to garbage collection.
>>>>
>>>> No, HEAD is protected against garbage collecting.  To be sure you
>>>> should name a branch when switching branches, though reflog would
>>>> protect you for 30 days (by default) even if you don't do that.
>>>
>>> So Git doesn't really support anonymous branching as part of a normal
>>> workflow.
>>
>> I perceive a certain logical fallacy here: you cannot switch between
>> anything anonymous because to switch, you should somehow identify
>> something to switch to--a name in whatever sense we put into this word.
>
> In Mercurial, you can just update to a particular changeset (and you
> identify that changeset by repository-local revision number or globally
> unique ID) and then commit again.  The point is that there's no need to
> give a label to a head in Mercurial (although you can if you want to, using
> Mercurial bookmarks, which are basically the same as what Git uses).
>
> Here's an example of anonymous branching:
>
>    c:\test>hg init
>
>    c:\test>echo test>foo
>
>    c:\test>hg commit --addremove -m initial
>    adding foo
>
>    c:\test>echo first>>foo
>
>    c:\test>hg commit -m first
>
>    c:\test>hg log
>    changeset:   1:3e895ec28d6c
>    tag:         tip
>    user:        tactical
>    date:        Mon Sep 26 01:39:46 2011 +0100
>    summary:     first
>
>    changeset:   0:b51644bb3450
>    user:        tactical
>    date:        Mon Sep 26 01:39:40 2011 +0100
>    summary:     initial
>
>    c:\test>hg update 0
>    1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>
>    c:\test>echo second>>foo
>
>    c:\test>hg commit -m second
>    created new head
>
>    c:\test>hg glog
>    @  changeset:   2:35c82a7e7de1
>    |  tag:         tip
>    |  parent:      0:b51644bb3450
>    |  user:        tactical
>    |  date:        Mon Sep 26 01:40:10 2011 +0100
>    |  summary:     second
>    |
>    | o  changeset:   1:3e895ec28d6c
>    |/   user:        tactical
>    |    date:        Mon Sep 26 01:39:46 2011 +0100
>    |    summary:     first
>    |
>    o  changeset:   0:b51644bb3450
>       user:        tactical
>       date:        Mon Sep 26 01:39:40 2011 +0100
>       summary:     initial
>
> I now have two anonymous branches, and these will never be garbage
> collected.  I can easily update to either branch with "hg update 1" or "hg
> update 2" (or "hg update 0" again, if i want to create yet another
> anonymous branch).
>
>> As I understand, by switching between branches in Mercurial you mean
>> switching between directories with clones;
>
> No.  Clones are a different topic.
>
>> As to branches, they do have names in Git but they are very loosely
>> coupled with their names: tag a tip of some branch (to still have a
>> handle on that tip commit) then delete that branch--there will be no
>> traces of that branch's name left, the branch's name is not encoded in
>> its history in any way.
>
> Git branch names are basically the same as Mercurial bookmarks.  The
> difference is that in Mercurial you don't *have* to use bookmarks.
>
>> The branch names is just a way to not mess with
>> SHA-1 names of commits (and to have references to those commits to keep
>> them out of consideration for garbage collection).
>> Hence the idea to demand support for anonymous branches in Git's model
>> is just unfounded.
>
> I think it's simply a weakness of Git.  There are zero problems with
> anonymous branching in Mercurial, and it's a very powerful and simple
> system.
>

I am no expert on this, however git can (of course) do 'anonymous
branching' just as simply as mercurial, with one caveat; for most
intents and purposes (as far as I have seen/heard discussed) git and
mercurial are homomorphic, and in the situations they are not git is
the more general system.

The flow that you are using for anonymous branching in mercurial is
easily reproducible in git, using detached heads. Checkout a revision
(note: not a ref)
  git checkout HEAD@{1}
hack + commit. Repeat as often as you like. Your concern is that these
will (eventually) be garbage collected. Again, I am not an expert in
this so please correct me if I have this incorrect, but the man page
for gc says:

       git-gc tries very hard to be safe about the garbage it collects. In
       particular, it will keep not only objects referenced by your current
       set of branches and tags, but also objects referenced by the index,
       remote tracking branches, refs saved by git-filter-branch in
       refs/original/, or reflogs (which may references commits in branches
       that were later amended or rewound).

As any commits you make in a detached state are in the reflog until
they expire (by default 30 days I think?) you have more than enough
time to decide if you want to keep the work - which you can do very
easily by assigning it a name. If the default time is not long enough,
simply extend it in your config
  git config gc.reflogExpire = 10000 years <- syntax might not be correct
The reason this is not true by default is that _most_ people don't
work exclusively in anonymous branches, and it is far nicer
performance wise to have git clean up for you.

So you don't *have* to use branches in git - they just make it much
easier to get around. They cost practically nothing to use, so I don't
really understand why you wouldn't want to for anything other than
just a quick throwaway test or scratch idea.

I hope that clears it up a little.

Andrew

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-26  1:34                           ` Andrew Ardill
@ 2011-09-26  1:42                             ` tactical
  0 siblings, 0 replies; 24+ messages in thread
From: tactical @ 2011-09-26  1:42 UTC (permalink / raw)
  To: git

Andrew Ardill wrote:

> As any commits you make in a detached state are in the reflog until
> they expire (by default 30 days I think?) you have more than enough
> time to decide if you want to keep the work - which you can do very
> easily by assigning it a name. If the default time is not long enough,
> simply extend it in your config
>   git config gc.reflogExpire = 10000 years <- syntax might not be correct

Thanks for your post, but, again, my point is that Git does not support
anonymous branching as part of a normal workflow.  Having X days until
detonation is hardly part of a normal workflow (even if X can be changed,
as you suggest).

Anyway, this thread's really going off topic, so I'll try not to reply
again.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: More Beginning Git Questions
  2011-09-26  0:56                         ` tactical
  2011-09-26  1:34                           ` Andrew Ardill
@ 2011-09-26 18:03                           ` Jakub Narebski
  1 sibling, 0 replies; 24+ messages in thread
From: Jakub Narebski @ 2011-09-26 18:03 UTC (permalink / raw)
  To: tactical; +Cc: git

tactical <a5158017@nepwk.com> writes:
> Konstantin Khomoutov wrote:
> 
>>>>> From what I read, detached heads are subject to garbage collection.
>>>>  
>>>> No, HEAD is protected against garbage collecting.  To be sure you
>>>> should name a branch when switching branches, though reflog would
>>>> protect you for 30 days (by default) even if you don't do that.
>>> 
>>> So Git doesn't really support anonymous branching as part of a normal
>>> workflow.
>> 
>> I perceive a certain logical fallacy here: you cannot switch between
>> anything anonymous because to switch, you should somehow identify
>> something to switch to--a name in whatever sense we put into this word.
> 
> In Mercurial, you can just update to a particular changeset (and you
> identify that changeset by repository-local revision number or globally
> unique ID) and then commit again.  The point is that there's no need to
> give a label to a head in Mercurial (although you can if you want to, using
> Mercurial bookmarks, which are basically the same as what Git uses).
> 
> Here's an example of anonymous branching:
> 
>     c:\test>hg init
> 
>     c:\test>echo test>foo
> 
>     c:\test>hg commit --addremove -m initial
>     adding foo
> 
>     c:\test>echo first>>foo
> 
>     c:\test>hg commit -m first
> 
>     c:\test>hg log
>     changeset:   1:3e895ec28d6c
>     tag:         tip
>     user:        tactical
>     date:        Mon Sep 26 01:39:46 2011 +0100
>     summary:     first
> 
>     changeset:   0:b51644bb3450
>     user:        tactical
>     date:        Mon Sep 26 01:39:40 2011 +0100
>     summary:     initial
> 
>     c:\test>hg update 0
>     1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> 
>     c:\test>echo second>>foo
> 
>     c:\test>hg commit -m second
>     created new head
> 
>     c:\test>hg glog
>     @  changeset:   2:35c82a7e7de1
>     |  tag:         tip
>     |  parent:      0:b51644bb3450
>     |  user:        tactical
>     |  date:        Mon Sep 26 01:40:10 2011 +0100
>     |  summary:     second
>     |
>     | o  changeset:   1:3e895ec28d6c
>     |/   user:        tactical
>     |    date:        Mon Sep 26 01:39:46 2011 +0100
>     |    summary:     first
>     |
>     o  changeset:   0:b51644bb3450
>        user:        tactical
>        date:        Mon Sep 26 01:39:40 2011 +0100
>        summary:     initial
> 
> I now have two anonymous branches, and these will never be garbage
> collected.  I can easily update to either branch with "hg update 1" or "hg
> update 2" (or "hg update 0" again, if i want to create yet another
> anonymous branch).

In my opinion the need to examine either log ('hg glog') or heads
('hg heads'?) to see how to switch to anonymous branch is a PITA
that far outweights the need to name branches (to give a temporary,
local-only branch name) in Git.
 
Nb. by using "detached HEAD" for anonymous branch I meant the
following:

  $ git checkout --detach
  $ ...
  $ <work on detached head>

  worth saving?

  Y. $ git branch -b t foo/temp
     $ git checkout <other branch>
    
  N. $ git checkout <other branch>

> > The branch names is just a way to not mess with
> > SHA-1 names of commits (and to have references to those commits to keep
> > them out of consideration for garbage collection).
> > Hence the idea to demand support for anonymous branches in Git's model
> > is just unfounded.
> 
> I think it's simply a weakness of Git.  There are zero problems with
> anonymous branching in Mercurial, and it's a very powerful and simple
> system.
 
IMVVVHO it is just remains of bad initial design decision of Mercurial
about representing branches ;-PPPPPPP

Only now Mercurial has something (transferable bookmarks) which
approaches flexibility and usability of Git branches.  It took them
how long... and even then there is a [supposedly] user-friendly but
flexibility-reducing notion that branch (bookmark) names are global.


Not that Git didn't and doesn't have its share of bad design decisions
(like autimatically committing a merge).

-- 
Jakub Narębski

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2011-09-26 18:04 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-23 14:41 More Beginning Git Questions Jon Forrest
2011-09-23 16:11 ` Matthieu Moy
2011-09-23 17:42 ` Jakub Narebski
2011-09-23 18:14   ` Jon Forrest
2011-09-23 18:44     ` Mihamina Rakotomandimby
2011-09-23 18:59     ` Jakub Narebski
2011-09-24 20:22     ` tactical
2011-09-24 20:53       ` Frans Klaver
2011-09-24 22:17         ` tactical
2011-09-24 22:59           ` Seth Robertson
2011-09-25  2:16             ` tactical
2011-09-25 13:22               ` Jakub Narebski
2011-09-25 20:23                 ` tactical
2011-09-25 20:58                   ` Jakub Narebski
2011-09-25 21:07                     ` tactical
2011-09-26  0:34                       ` Konstantin Khomoutov
2011-09-26  0:56                         ` tactical
2011-09-26  1:34                           ` Andrew Ardill
2011-09-26  1:42                             ` tactical
2011-09-26 18:03                           ` Jakub Narebski
2011-09-24 21:10       ` Jakub Narebski
2011-09-24 22:10         ` tactical
2011-09-25 13:24           ` Jakub Narebski
2011-09-23 18:47 ` Junio C Hamano

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.