Git development
 help / color / mirror / Atom feed
* Re: [PATCH] MSVC: Windows-native implementation for subset of Pthreads API
From: Nicolas Pitre @ 2009-11-05 22:15 UTC (permalink / raw)
  To: Andrzej K. Haczewski; +Cc: kusmabite, git, Johannes Sixt
In-Reply-To: <16cee31f0911051238v71ec4b57s415efb7bb48999d1@mail.gmail.com>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 990 bytes --]

On Thu, 5 Nov 2009, Andrzej K. Haczewski wrote:

> 2009/11/5 Nicolas Pitre <nico@fluxnic.net>:
> > Why not?  At least gcc is quite happy with such a construct.  It
> > probably makes a copy of the stack before passing it though.

"a copy of the struct" I meant here.

> Err... my mind is rotted with all that ugly java, c#, python and ruby,
> even c++. I should start taking some medications I suppose... what was
> I thinking is that C can't copy-construct a struct. Damn, too much sun
> (of java fame)...
> 
> That way I rediscovered simple struct construct...man I missed C so much :)

Welcome back !  ;-)

> Anyway, the solution with passing pthread_t as pointer saves some
> stack, so it's probably not that bad.

Yep, just what I said.  Normally if you pass a structure to a function, 
it will be copied beforehand so modifications by the callee won't be 
seen by the caller.  But in this case we don't care, hence passing the 
original structure address is more efficient.


Nicolas

^ permalink raw reply

* Re: Preserving branches after merging on ancestor
From: Jonathan Nieder @ 2009-11-05 22:30 UTC (permalink / raw)
  To: Richard Lee; +Cc: git
In-Reply-To: <26217077.post@talk.nabble.com>

Hi Richard,

Richard Lee wrote:
 
> One way of getting round this problem is to use empty commits on the master
> branch, as shown below.
> 
> *   6fc04b5 Merge branch 'feature2'
> |\
> | * 07a117b stuff on feature2
> * | 52f5ba1 Empty commit
> |/
> *   5deaa93 Merge branch 'feature1'
> |\
> | * b163b17 stuff on feature1
> | * 53bb820 stuff on feature1
> | * c9ef14c stuff on feature1
> * | 34227a3 Empty commit
> |/
> * e88d332 Init
> 
> But is this correct? It seems rather hackish to create empty commits on the
> master branch just to historically preserve commits on a seperate branch.
> Should I be using feature branches in git like this or another way? For
> example more informative commit messages. 

As Eric said, you can avoid the empty commits by passing 'git merge'
the --no-ff option, which would give the history I think you intend:

*   26749ab Merge branch 'feature2'
|\
| * b9cd8ff stuff on feature2
|/
*   829ba2c Merge branch 'feature1'
|\
| * b163b17 stuff on feature1
| * 53bb820 stuff on feature1
| * c9ef14c stuff on feature1
|/
* e88d332 Init

But doing this misses some of the main benefits of feature branches
imho.

If you base each feature branch on the stable release or features it
depends on instead, this gives you the freedom to merge one feature without
the others to another branch.  For example:

# wouldn’t feature1 be neat? let me try it.
git checkout -b feature1 v1.0
hack hack hack
# looks good.
git commit -a

# how about an unrelated feature2?
git checkout -b feature2 v1.0
hack hack hack
# looks good.
git commit -a

# but do they work?
git checkout v1.0; # detach head for testing [1]
git merge feature1 feature2
make check
# hmm, these don’t seem to work well together
... (investigating some more)

# looks like feature1 is not ready for prime time
# so let’s just use feature2 for now.
git checkout master
git merge feature2
git branch -d feature2
make check
# looks good; better publish it.
git push origin master

v1.0 --- feature1
    \
     \-- feature2 [master]

As a nice side-effect, if you work this way then you can develop
feature2 without being distracted by new bugs introduced by feature1.

With many features built this way, the revision graph starts to give
some hints about relationships between features developed around the
same time.  For example, with the history

v1.0 --- feature1 --- feature2 -- feature4 -- feature6 - v1.1
                               \                        /
                                -- feature5 ------------

feature4 and feature5 are not likely to be closely related, but
feature4 and feature6 might be.  The exact history of merges is less
important than the general "shape" of the graph.

Thanks for the food for thought.

Hope that helps,
Jonathan

[1] See <http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html#_detached_head>.

^ permalink raw reply

* Re: Automatically remote prune
From: Jay Soffian @ 2009-11-05 23:09 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: John Tapsell, Git List
In-Reply-To: <7v3a4sagau.fsf@alter.siamese.dyndns.org>

On Thu, Nov 5, 2009 at 3:05 PM, Junio C Hamano <gitster@pobox.com> wrote:
> The necessary change to "git fetch" shouldn't be too hard to code, as we
> are already doing this in mirror mode.

Actually, mirror mode applies to push only. Unless I'm missing
something obvious.

Thus, adding prune to builtin-fetch duplicates the logic from
builtin-remote, unless I do some refactoring. Hmph, I was hoping for a
15 minute patch. :-(

j.

^ permalink raw reply

* Re: Preserving branches after merging on ancestor
From: Björn Steinbrink @ 2009-11-05 23:28 UTC (permalink / raw)
  To: Jonathan Nieder; +Cc: Richard Lee, git
In-Reply-To: <20091105223004.GA3224@progeny.tock>

On 2009.11.05 16:30:04 -0600, Jonathan Nieder wrote:
> But doing this misses some of the main benefits of feature branches
> imho.
> 
> If you base each feature branch on the stable release or features it
> depends on instead, this gives you the freedom to merge one feature without
> the others to another branch.

I guess Richard took the "branch topic1, merge topic1, branch topic2,
merge topic2" thing just as an example because that ends up with two
fast-forwards. And your example _still_ has such a fast-forward.

> For example:
> 
> # wouldn’t feature1 be neat? let me try it.
> git checkout -b feature1 v1.0
> hack hack hack
> # looks good.
> git commit -a
> 
> # how about an unrelated feature2?
> git checkout -b feature2 v1.0
> hack hack hack
> # looks good.
> git commit -a
> 
> # but do they work?
> git checkout v1.0; # detach head for testing [1]
> git merge feature1 feature2
> make check
> # hmm, these don’t seem to work well together
> ... (investigating some more)
> 
> # looks like feature1 is not ready for prime time
> # so let’s just use feature2 for now.
> git checkout master
> git merge feature2
> git branch -d feature2
> make check
> # looks good; better publish it.
> git push origin master
> 
> v1.0 --- feature1
>     \
>      \-- feature2 [master]

And here you got a fast-forward of master to feature2, i.e. linear
history, which is what Richard was trying to avoid.

Instead of:

A---B---C---D---E (topic2) (master)
     \
      F---G---H (topic1)

He wants:

      F---G---H (topic1)
     /
A---B-----------M (master)
     \         /
      C---D---E (topic2)

So he can see at which point topic2 got merged. This allows to ask "which
commits got merged here" (and for a merge-once topic branch this means:
Which commits are related to that topic), by using for example:

git log M^1..M^2 # Will show C, D and E

In the fast-forward case, there's no way to get that without manually
figuring out where the topic branch started.

Björn

^ permalink raw reply

* Re: [PATCH v2 09/13] Honour the refspec when updating refs after  import
From: Sverre Rabbelier @ 2009-11-05 23:51 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: Git List, Johannes Schindelin, Johan Herland
In-Reply-To: <alpine.LNX.2.00.0911050145010.14365@iabervon.org>

Heya,

On Thu, Nov 5, 2009 at 07:53, Daniel Barkalow <barkalow@iabervon.org> wrote:
> Here's a patch (on my original series, which doesn't seem to be in pu any
> more, but should be floating around somewhere).

Why didn't you just base it against sr/vcs-helper which is currently
in pu, now I have to try to find where your original series was, and
rebase this patch against it. Assuming your main goal was to
illustrate the direction you think we should go it would have been a
lot easier that way.

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: [PATCH v2 13/13] Add Python support library for remote helpers
From: Sverre Rabbelier @ 2009-11-06  0:14 UTC (permalink / raw)
  To: Johan Herland
  Cc: Git List, Johannes Schindelin, Daniel Barkalow, David Aguilar
In-Reply-To: <200911050855.01164.johan@herland.net>

Heya,

On Thu, Nov 5, 2009 at 08:55, Johan Herland <johan@herland.net> wrote:
> There are a few typos in the above.

Thanks, fixed locally, will include this in the next version.

> Otherwise it all looks good. Nice work!

Cool, thanks!

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: Automatically remote prune
From: Petr Baudis @ 2009-11-06  0:16 UTC (permalink / raw)
  To: John Tapsell; +Cc: Junio C Hamano, Git List
In-Reply-To: <43d8ce650911050005l6d120cb0h374f3c04b3948b25@mail.gmail.com>

On Thu, Nov 05, 2009 at 05:05:50PM +0900, John Tapsell wrote:
> 2009/11/5 Junio C Hamano <gitster@pobox.com>:
> > John Tapsell <johnflux@gmail.com> writes:
> > "what the benefits are to give this information _in the 'branch' output_"
> > was what I meant.  From the part you omitted from my message:
> 
> I omitted it just because, imho, it's not what I 'care about'.  I'm
> not trying to help advanced users (Users that _want_ to keep
> remotes/origin/* clean and users that _want_ to be careful to not lose
> commits are both advanced users, imho).  I'm just interested in
> reducing confusion for non-advanced users.  So either not-showing
> removed remote branches by default, or showing them but marking them
> as deleted.

Maybe, if your users want to know "what branches does the remote repo
have" instead of "what branches does my 'image' of the remote repo has",
just teach them to run

	git remote show origin

instead of

	git branch -r origin

as mentioned earlier by Junio?

Of course, users would still need to realize the actual meaning of the
commands and the fact that Git _does_ keep a distinctive 'image of
remote repository', so this may not be the most intuitive solution.

-- 
				Petr "Pasky" Baudis
A lot of people have my books on their bookshelves.
That's the problem, they need to read them. -- Don Knuth

^ permalink raw reply

* Re: Automatically remote prune
From: Petr Baudis @ 2009-11-06  0:17 UTC (permalink / raw)
  To: Jay Soffian; +Cc: Junio C Hamano, John Tapsell, Git List
In-Reply-To: <76718490911051509r65af2dd2k2574e2e521fed6f2@mail.gmail.com>

On Thu, Nov 05, 2009 at 06:09:03PM -0500, Jay Soffian wrote:
> On Thu, Nov 5, 2009 at 3:05 PM, Junio C Hamano <gitster@pobox.com> wrote:
> > The necessary change to "git fetch" shouldn't be too hard to code, as we
> > are already doing this in mirror mode.
> 
> Actually, mirror mode applies to push only. Unless I'm missing
> something obvious.

Perhaps you are, mirror mode applies to fetch as well; that's how e.g.
repo.or.cz mirror mode is done currently.

				Petr "Pasky" Baudis

^ permalink raw reply

* Re: [PATCH v2 09/13] Honour the refspec when updating refs after  import
From: Daniel Barkalow @ 2009-11-06  0:19 UTC (permalink / raw)
  To: Sverre Rabbelier
  Cc: Git List, Johannes Schindelin, Johan Herland, Junio C Hamano
In-Reply-To: <fabb9a1e0911051551r2e13cfb9me0e668adb962f6bd@mail.gmail.com>

On Fri, 6 Nov 2009, Sverre Rabbelier wrote:

> Heya,
> 
> On Thu, Nov 5, 2009 at 07:53, Daniel Barkalow <barkalow@iabervon.org> wrote:
> > Here's a patch (on my original series, which doesn't seem to be in pu any
> > more, but should be floating around somewhere).
> 
> Why didn't you just base it against sr/vcs-helper which is currently
> in pu, now I have to try to find where your original series was, and
> rebase this patch against it. Assuming your main goal was to
> illustrate the direction you think we should go it would have been a
> lot easier that way.

I didn't understand the version of my patch that contains your changes, 
and I didn't know what was in it. I don't know why Junio squashed your 
changes into my patch, particularly when I disagreed with those changes.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Git & Project Workflow
From: Tommy Wang @ 2009-11-06  0:19 UTC (permalink / raw)
  To: git

Hi,

I'm trying to set up a project using git, and I'm having a hard time
figuring out the best way to implement one of my workflows.

Lets say I have a repository "main".  Some of my developers will have
full access to this repository, while others should have access only
to certain parts of it (and, no, unfortunately the files are scattered
all over the place, and reorganizing isn't an option, so I can't use
subtrees).

I've attempted to solve this project by cloning the project into
another repository "limited".  Now, half of my developers can work off
from "main", while the other half can work from "limited".
Incidentally, its okay that the original source is visible in limited,
I just don't want the work we put into "main" to show up in "limited".

So, lets say my "main" developer makes some changes to the project.
Some of his changes are to kept in "main" only, while other changes
need to be pushed into "limited".  I can maybe force developers to
keep changes in common files in separate commits, and just cherry pick
them into "limited".  "Limited" developers can then pull those changes
into his local repository, resolve conflicts, (rebase), and push them
back into "limited".  At some point later in time, lets suppose we
need to push changes made in limited back to main.  So, our main
developers will cherry pick again the newest changes into limited (to
keep the conflicts down).  Limited developers will then
commit/resolve/rebase their work into limited, and let the main
developers know that they're ready.  The main developers will now pull
from limited -- and since we (likely) haven't changed main, the pull
should be pretty conflict free (git does keep track of cherry-commits
in merges, right?).

My question is, is cherry-picking really the best way to do this?
What I'd really like to do is to create the limited repository by
doing a filter-branch and removing secure files out of the repository
entirely.  After doing this, though, it makes it difficult/impossible
to move changes between the two repositories.  I tried a number of
approaches, including trying to graft the two repositories together
after the filter-branch to make push/pull work as simple
merges/fast-forwards.  I would have to figure out way to filter
commits to make sure that main doesn't push a secure file into
limited, and that limited doesn't try to do something silly like
creating a secure file.  Perhaps I could use filter-branch to rewrite
these commits as well.  But, being that filter-branch totally changes
the commit ids, I figure that this approach really doesn't have any
merit.

I also considered doing something like this:

# create main & limited from upstream source
git clone upstream main
git clone main limited

# remove secure files from limited
cd limited
git rm -r secure files
git commit

# fake a merge to keep histories correct
cd main
git pull -s ours limited

# pulling from limited worked well, and would only get changes made after the rm
cd main
git pull limited master

# pull from main didn't work so well --> but I probably should be
cherry-picking here anyway?
cd limited
git pull main master

I'm not sure why I'm trying so hard to avoid cherry-picking.  Probably
due to the fact that developers need to be more intimate with git, and
that it takes considerably more time to look through a list of
commits, and pick out the ones that can be moved from main -> limited.

Is there a way to generate a list of commits based on a list of files
(paths aren't good enough, since my files are scattered all over the
place) that can be found in main but not limited?  Perhaps I can write
a script that can be used to automate the cherry-picking from main ->
limited.  If we run this script right after we resolve all the
conflicts from a limited -> main merge, we should be able to avoid all
conflicts.

Anyway, I'm hoping for some thoughts/direction on how I may be able to
solve my problem.  Perhaps there is a magical solution that is plainly
obvious to someone with more git experience?

Thanks,
Tommy

^ permalink raw reply

* Re: [PATCH v2 09/13] Honour the refspec when updating refs after  import
From: Sverre Rabbelier @ 2009-11-06  0:28 UTC (permalink / raw)
  To: Daniel Barkalow
  Cc: Git List, Johannes Schindelin, Johan Herland, Junio C Hamano
In-Reply-To: <alpine.LNX.2.00.0911051917100.14365@iabervon.org>

Heya,

On Fri, Nov 6, 2009 at 01:19, Daniel Barkalow <barkalow@iabervon.org> wrote:
> I didn't understand the version of my patch that contains your changes,
> and I didn't know what was in it.

Either way, I managed to apply your patch, will send a new version of
the series tomorrow.

> I don't know why Junio squashed your
> changes into my patch, particularly when I disagreed with those changes.

Junio didn't squash anything, it's just that pu still contains v4 of
the series, in which I had squashed my changes in.

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Bug in git remote prune?
From: Jay Soffian @ 2009-11-06  0:34 UTC (permalink / raw)
  To: git

Let's say you've got the following tracking branches:

refs/remotes/origin/master
refs/remotes/origin/next
refs/remotes/origin/ghost

And origin has only "master" and "next" (ghost has been removed upstream).

Further, let's say you've got a refspec of:

[remote "origin"]
  fetch = +refs/heads/master:refs/remotes/origin/master

What should "git remote prune origin" do?

In my opinion, it should prune "next" and "ghost".  "ghost" is gone
from upstream, so that's obvious. I think "next" should also be pruned
because the refspec indicates the user is no longer interested in it.

Currently it doesn't do anything (it only considers "master" per the
refspec, which is still on origin, so it doesn't think there is
anything to prune).

Thoughts?

j.

^ permalink raw reply

* Re: [PATCH v2 09/13] Honour the refspec when updating refs after  import
From: Daniel Barkalow @ 2009-11-06  0:37 UTC (permalink / raw)
  To: Sverre Rabbelier
  Cc: Git List, Johannes Schindelin, Johan Herland, Junio C Hamano
In-Reply-To: <fabb9a1e0911051628v2ba15be2s9c3fb06879607cc0@mail.gmail.com>

On Fri, 6 Nov 2009, Sverre Rabbelier wrote:

> Heya,
> 
> On Fri, Nov 6, 2009 at 01:19, Daniel Barkalow <barkalow@iabervon.org> wrote:
> > I didn't understand the version of my patch that contains your changes,
> > and I didn't know what was in it.
> 
> Either way, I managed to apply your patch, will send a new version of
> the series tomorrow.

Does it make sense now in what it's trying to do? (And does it turn out to 
work?) I'm fairly certain it's the easiest way to make the remote appear 
most natural to the rest of git, but I don't actually have code that wants 
to use it, so I wouldn't know if this just wouldn't work for hg or 
something.

> > I don't know why Junio squashed your
> > changes into my patch, particularly when I disagreed with those changes.
> 
> Junio didn't squash anything, it's just that pu still contains v4 of
> the series, in which I had squashed my changes in.

Oh, okay. You probably shouldn't squash un-acked changes into other 
people's patches when taking over their series.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Re: Automatically remote prune
From: Jay Soffian @ 2009-11-06  0:38 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Junio C Hamano, John Tapsell, Git List
In-Reply-To: <20091106001751.GF17748@machine.or.cz>

On Thu, Nov 5, 2009 at 7:17 PM, Petr Baudis <pasky@suse.cz> wrote:
> On Thu, Nov 05, 2009 at 06:09:03PM -0500, Jay Soffian wrote:
>> Actually, mirror mode applies to push only. Unless I'm missing
>> something obvious.
>
> Perhaps you are, mirror mode applies to fetch as well; that's how e.g.
> repo.or.cz mirror mode is done currently.

Can you please be more specific? There is no mention of mirror in
builtin-fetch.c, only builtin-push.c. Further, the docs for
"remote.<name>.mirror" indicate it's a push option only.

So please explain what you mean by "that's how repo.or.cz mirror mode is done".

Cluelessly yours,

j.

^ permalink raw reply

* Re: [PATCH] gitk: disable checkout of remote branch
From: Junio C Hamano @ 2009-11-06  0:45 UTC (permalink / raw)
  To: Jeff King; +Cc: Junio C Hamano, Sverre Rabbelier, Tim Mazid, git
In-Reply-To: <20091105074808.GA12114@coredump.intra.peff.net>

Jeff King <peff@peff.net> writes:

>> Isn't it quite different?  What's in 'next' for 1.7.0 is to guess the
>> user's intention when:
>
> Sorry, yes, I just saw Sverre's comment and misread the original
> proposal.  Checking out "$remote/$branch" will still detach the HEAD,
> and I don't think anybody has a previous proposal to change that.

Heh, I think both of us forgot that we decided it is safe enough not to
wait for 1.7.0 already, because the situation this kicks in has always
resulted in an error.  We have it in master since e3de372 (Merge branch
'jc/checkout-auto-track', 2009-10-30).

^ permalink raw reply

* Re: Preserving branches after merging on ancestor
From: Jonathan Nieder @ 2009-11-06  1:09 UTC (permalink / raw)
  To: Björn Steinbrink; +Cc: Richard Lee, git
In-Reply-To: <20091105232848.GA1939@atjola.homenet>

Björn Steinbrink wrote:

> I guess Richard took the "branch topic1, merge topic1, branch topic2,
> merge topic2" thing just as an example because that ends up with two
> fast-forwards.

Hmm, I found Richard’s example pretty realistic.  I used to work like
that, and I don’t think I am the only one.

> And your example _still_ has such a fast-forward.

Yep, if you really want to avoid fast-forwards, please use "--no-ff"!

But what I was trying to make clear was that in some workflows, the
fast-forwards are not so harmful.  They even make the history a little
cleaner (easier to read and understand).

> Instead of:
> 
> A---B---C---D---E (topic2) (master)
>      \
>       F---G---H (topic1)
> 
> He wants:
> 
>       F---G---H (topic1)
>      /
> A---B-----------M (master)
>      \         /
>       C---D---E (topic2)
> 
> So he can see at which point topic2 got merged. This allows to ask "which
> commits got merged here" (and for a merge-once topic branch this means:
> Which commits are related to that topic), by using for example:
> 
> git log M^1..M^2 # Will show C, D and E

You can get the same information locally even with a fast-forward:

git log master@{1}..master

But to someone reading the published history, it is not available.
Depending on your way of working, this may or may not be reasonable.

Perhaps your merge commit messages contain important information about
the branch’s overall purpose and provenance, which would be impossible
if there is no merge commit.

On the other hand, if the goal is just to present the fact of a merge,
to explain where a patch falls in the larger scheme of things, then
how large a chunk of changes I decided to call a feature does not seem
too important.

Imagine a patch series, cleaning up some ugly code that has been
bothering me for a while:

 base [master] --- A --- B --- C [cleanup]

It looks good, so I merge to master with --no-ff.

 base --------- D [master]
     \         /
      A---B---C [cleanup]

Looking at that code inspires me to build a new feature that is much
easier with the cleaned up version.  So I fork a branch from cleanup
(Or master?  Their content is the same, but somehow I choose one) and
write some patches for the new feature.

 base --------- D [master]
     \         /
      A---B---C [cleanup] --- E --- F --- G

It looks good, so I merge.

 base --------- D --------- H [master]
     \         /           /
      A---B---C---E---F---G

Is this really any easier to read than base---A---B---C---E---F---G?
In hindsight, was this logically really two series, or is the D commit
extra cruft?

Almost always, a fast-forward comes from a continuation of this kind,
since that is what it means for a commit to be the logical commit to
fork from.

Of course, these things are a matter of taste.  I just wanted to
explain why a fast-forward could at least sometimes be the right
result from merging a topic branch (and why, in practice, some people
never end up needing to use --no-ff).

Regards,
Jonathan

^ permalink raw reply

* Re: Bug in git remote prune?
From: Junio C Hamano @ 2009-11-06  1:36 UTC (permalink / raw)
  To: Jay Soffian; +Cc: git
In-Reply-To: <76718490911051634w2d364b73m567e73039508c857@mail.gmail.com>

Jay Soffian <jaysoffian@gmail.com> writes:

> Let's say you've got the following tracking branches:
>
> refs/remotes/origin/master
> refs/remotes/origin/next
> refs/remotes/origin/ghost
>
> And origin has only "master" and "next" (ghost has been removed upstream).
>
> Further, let's say you've got a refspec of:
>
> [remote "origin"]
>   fetch = +refs/heads/master:refs/remotes/origin/master
>
> What should "git remote prune origin" do?
>
> In my opinion, it should prune "next" and "ghost".  "ghost" is gone
> from upstream, so that's obvious. I think "next" should also be pruned
> because the refspec indicates the user is no longer interested in it.
>
> Currently it doesn't do anything (it only considers "master" per the
> refspec, which is still on origin, so it doesn't think there is
> anything to prune).

In your scenario, tracking branches for next and ghost couldn't have come
from the refspec you have in the configuration, but they do exist.  The
user has added them on purpose, perhaps by temporarily using wildcard
refspec, or perhaps by giving a refspec from the command line.

It does not matter how they got there, but the important thing to keep in
mind is that, even if the remote had refs/heads/{next,ghost}, we wouldn't
update it if we ran "git fetch" now.

In this situation, "git remote prune" should never prune 'next' nor
'ghost'.  If we were to implement auto-pruning in 'git fetch', it should
behave the same way.

I would define the logic to decide if refs/remotes/REMOTE/BRANCH is stale
to be:

 * See if there exists a refspec (either wildcard or concrete) that may
   cause "git fetch" to update the tracking branch in question, if the
   remote side had an appropriate ref.

   If there is no such refspec, stop here.  It is not stale.

   In your example, when considering refs/remotes/origin/master, there is
   such a refspec, and the "appropriate ref" is "refs/heads/master" on
   their side.  When considering refs/remotes/origin/{next,ghost}, there
   is none.  You stop here.

 * Then see if that ref exists at the remote side.  If it exists, stop
   here.  It means "git fetch" would update the tracking branch in
   question, so it is not stale.

   In your example, when considering refs/remotes/origin/master, the
   matching remote ref 'refs/heads/master' exists, so our tracking ref is
   not stale.

 * Otherwise, it is stale, and we can prune it.

Imagine a hypothetical "git fetch" that understands a ref with a magic
value 0{40} to signal "this ref is gone", and imagine what happens if the
origin had 'ghost' that has such a magic SHA-1 in it.  It would become
easier to understand how the above logic works.

 - When you issue "git fetch" under the condition of your example, think
   what would happen to 'next' (which has an ordinary value, not the magic
   "delete this" request).  Nothing happens.  We do not update it.

 - Nothing happens to 'ghost' either when you issue "git fetch".  It does
   not matter if that ref has this magic 'delete this' value.

Nothing happens because we were told by the refspec not to even look at
these refs/heads/{next,ghost} refs on the other side.

^ permalink raw reply

* Re: how to rebase backwards
From: bill lam @ 2009-11-06  1:43 UTC (permalink / raw)
  To: David,
	=?iso-8859-1?Q?K=E5gedal_=3Cdavidk=40lysator=2Eliu=2Ese=3E?=
  Cc: Junio C Hamano, git
In-Reply-To: <877hu4zsyq.fsf@lysator.liu.se>

On Thu, 05 Nov 2009, David Kågedal wrote:
> command. For instance git log --graph master...deply whill show you both
> branches, starting from their common ancestor. "git merge-base deploy
> master" will tell you that the common ancestor is. Etc.

David, thank you for this info.

-- 
regards,
====================================================
GPG key 1024D/4434BAB3 2008-08-24
gpg --keyserver subkeys.pgp.net --recv-keys 4434BAB3

^ permalink raw reply

* Re: Bug in git remote prune?
From: Jay Soffian @ 2009-11-06  1:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vvdho5t9s.fsf@alter.siamese.dyndns.org>

On Thu, Nov 5, 2009 at 8:36 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Nothing happens because we were told by the refspec not to even look at
> these refs/heads/{next,ghost} refs on the other side.

Gotcha, and that's all you had to say, but I appreciate the long
explanation. :-)

j.

^ permalink raw reply

* Re: Preserving branches after merging on ancestor
From: Björn Steinbrink @ 2009-11-06  2:10 UTC (permalink / raw)
  To: Jonathan Nieder; +Cc: Richard Lee, git
In-Reply-To: <20091106010947.GB4425@progeny.tock>

On 2009.11.05 19:09:48 -0600, Jonathan Nieder wrote:
> Björn Steinbrink wrote:
> 
> > I guess Richard took the "branch topic1, merge topic1, branch topic2,
> > merge topic2" thing just as an example because that ends up with two
> > fast-forwards.
> 
> Hmm, I found Richard’s example pretty realistic.  I used to work like
> that, and I don’t think I am the only one.
> 
> > And your example _still_ has such a fast-forward.
> 
> Yep, if you really want to avoid fast-forwards, please use "--no-ff"!
> 
> But what I was trying to make clear was that in some workflows, the
> fast-forwards are not so harmful.  They even make the history a little
> cleaner (easier to read and understand).
> 
> > Instead of:
> > 
> > A---B---C---D---E (topic2) (master)
> >      \
> >       F---G---H (topic1)
> > 
> > He wants:
> > 
> >       F---G---H (topic1)
> >      /
> > A---B-----------M (master)
> >      \         /
> >       C---D---E (topic2)
> > 
> > So he can see at which point topic2 got merged. This allows to ask "which
> > commits got merged here" (and for a merge-once topic branch this means:
> > Which commits are related to that topic), by using for example:
> > 
> > git log M^1..M^2 # Will show C, D and E
> 
> You can get the same information locally even with a fast-forward:
> 
> git log master@{1}..master

And after two weeks, you'll dig through the reflog to find the right
entries? Come on... And (as you said yourself below) everyone else
(including yourself in a different clone of that repo) doesn't have that
reflog entry anyway.

> But to someone reading the published history, it is not available.
> Depending on your way of working, this may or may not be reasonable.
> 
> Perhaps your merge commit messages contain important information about
> the branch’s overall purpose and provenance, which would be impossible
> if there is no merge commit.

The actual commits that make up the topic should have descriptive enough
commit messages to make extra "why merge this" messages shouldn't be
required. But merge commits provide a way of giving a high-level
overview of the history of a project.

> On the other hand, if the goal is just to present the fact of a merge,
> to explain where a patch falls in the larger scheme of things, then
> how large a chunk of changes I decided to call a feature does not seem
> too important.

For example in git.git, I can do "git log --first-parent
..origin/master" to get a high-level log of what happened. And then I
might see commit b7eb912b0, which is "Merge branch ja/fetch-doc". So I
know "OK, there were some doc updates", without having to crawl through
the individual commits.

And if I decide that for _this_ topic, I care to see what got merged, I
can do: git log b7eb912b0^1..b7eb912b0^2

Had this been a fast-forward, even the --first-parent history would
throw the individual commits at me, giving me less of a high-level
overview.

> Imagine a patch series, cleaning up some ugly code that has been
> bothering me for a while:
> 
>  base [master] --- A --- B --- C [cleanup]
> 
> It looks good, so I merge to master with --no-ff.
> 
>  base --------- D [master]
>      \         /
>       A---B---C [cleanup]
> 
> Looking at that code inspires me to build a new feature that is much
> easier with the cleaned up version.  So I fork a branch from cleanup
> (Or master?  Their content is the same, but somehow I choose one) and
> write some patches for the new feature.
> 
>  base --------- D [master]
>      \         /
>       A---B---C [cleanup] --- E --- F --- G
> 
> It looks good, so I merge.
> 
>  base --------- D --------- H [master]
>      \         /           /
>       A---B---C---E---F---G
> 
> Is this really any easier to read than base---A---B---C---E---F---G?
> In hindsight, was this logically really two series, or is the D commit
> extra cruft?

Choosing "cleanup" as the starting point for an unrelated topic branch
(after all "cleanup" was already merged, so there's absolutely no reason
to base a new topic on it) is wrong. That history looks as if E,F,G was
a second part of the same topic branch.

I'd have done:

              E---F---G (topic2)
             /         \
0-----------D-----------H (master)
 \         /
  A---B---C (cleanup)

And then I could do "git log --first-parent master" to see H and D
(high-level view), and "git log H^1..H^2" or "git log D^1..D^2" to get a
low-level view at the merged topics.

Neither of which I could do with "0---A---B---C---E---F---G". With that,
I'd have to manually looking up the start/end points of each topic.

> Almost always, a fast-forward comes from a continuation of this kind,
> since that is what it means for a commit to be the logical commit to
> fork from.

Hm? I don't get that one. The "continuation" would be that you started
the second topic branch from the first topic branch, right? And that
caused the merge to "master" _not_ to be a fast-forward. So I'm somewhat
confused there.

> Of course, these things are a matter of taste.  I just wanted to
> explain why a fast-forward could at least sometimes be the right
> result from merging a topic branch (and why, in practice, some people
> never end up needing to use --no-ff).

Sure, fast-forwards can be the right thing, e.g. when you have a
(possibly useless) branch head "master" that you update by pulling. In
such a case merge commits would only lead to useless clutter. But
Richard wants to see where topic branches got merged (to be still able
to see what got merged in the future), and yeah, that's a matter of
taste. But you argued that using --no-ff would "[miss] some of the main
benefits of feature branches", which is simply not true.

Björn

^ permalink raw reply

* suggestions for local configs?
From: Tim Rupp @ 2009-11-06  3:11 UTC (permalink / raw)
  To: git

Hi list, I'm wrestling with a question and figured that someone on the
list may have some suggestions that have worked for them.

I have a piece of software that has default and local configuration
files. The default files ship with the tarball. The local files are
copied over from the default folder during installation and can be
modified for a particular install.

I clone my source repo on my test and prod systems, but have gotten in
the bad habit of versioning the local configuration files. My (albeit
pathetic) excuse is that when I test the code I may accidentally dork
with the local config files and need to revert back to the correct ones.

At the same time though, I do want to version said local configs in
something so that if changes are made and they need to be backed out, it
can be done and there is the commit log that keeps track of what changed.

So the question is

- Can anyone suggest good ways of setting up git to track both the code
and local configs without making a whole new repository (code repo and
code config repo)

If not, any other suggestions are welcome and I'll consider how best to
make them work in my environment.

I've briefly skimmed through the pro git book online and considered sub
modules and sub-tree merging, but the kicker is that I may need to push
the whole kit-n-kaboodle master repo to remote git servers and those two
approaches sound hairy.

Any help is appreciated.

Thanks,
Tim

^ permalink raw reply

* Re: Preserving branches after merging on ancestor
From: Jonathan Nieder @ 2009-11-06  5:03 UTC (permalink / raw)
  To: Björn Steinbrink; +Cc: Richard Lee, git
In-Reply-To: <20091106021038.GA27206@atjola.homenet>

Björn Steinbrink wrote:

> For example in git.git, I can do "git log --first-parent
> ..origin/master" to get a high-level log of what happened. And then I
> might see commit b7eb912b0, which is "Merge branch ja/fetch-doc". So I
> know "OK, there were some doc updates", without having to crawl through
> the individual commits.

Yep, fast-forward merges do ruin the --first-parent log.  Thanks for
the reminder.

>> Of course, these things are a matter of taste.  I just wanted to
>> explain why a fast-forward could at least sometimes be the right
>> result from merging a topic branch (and why, in practice, some people
>> never end up needing to use --no-ff).
> 
> Sure, fast-forwards can be the right thing, e.g. when you have a
> (possibly useless) branch head "master" that you update by pulling. In
> such a case merge commits would only lead to useless clutter.

I hope this use case becomes less important as git’s UI improves.  To
track unmodified upstream sources, a simple 'git checkout' to get
up-to-date is much simpler, except that "git branch" does not display
the current branch any more.  Using 'git pull' for the daily update
makes for a distractingly merge-heavy history once one has commits of
one’s own.

A similar use case won’t disappear: asking someone else to resolve a
merge for you and pulling the result.

For both these tasks, --ff-only might give better behavior.

In other cases, I would guess some people would always want --no-ff
and others never.  Apparently, there is a configuration option to
support this: add a line "mergeoptions = --no-ff" (or "mergeoptions =
--ff") to a [branch "master"] section in .git/config or ~/.gitconfig.

> But
> Richard wants to see where topic branches got merged (to be still able
> to see what got merged in the future), and yeah, that's a matter of
> taste. But you argued that using --no-ff would "[miss] some of the main
> benefits of feature branches", which is simply not true.

I spoke imprecisely; I should have said that if most merges are
candidates for fast-forwarding, this suggests feature branches are not
being used in the best way, and --no-ff just makes that situation more
tolerable.

Then your response pushed me towards the question of whether --no-ff
is a good idea in general, and I got distracted. :)  Sorry for the
confusion, and thanks for the insights.

Regards,
Jonathan

^ permalink raw reply

* [PATCH/RFC 0/3] teach fetch --prune
From: Jay Soffian @ 2009-11-06  5:10 UTC (permalink / raw)
  To: git; +Cc: Jay Soffian

This is just a start so I can get some feedback. Some things still missing:

1) "git remote prune <remote>" calls warn_dangling_symref(), but 
"git fetch --prune" does not. I ran out of time tonight to refactor 
warn_dangling_symref() to do something more intelligent than just spew to
stdout (which doesn't get along with fetch, which spews to stderr...).

2) Perhaps "git remote update --prune" should be refactored to call 
"git fetch --prune". If so, then fetch should gain a "--prune-only" option
so that "git remote prune" can just call "got fetch --prune-only".

3) Perhaps add a config option for users who wish to prune by default.

Thoughts, comments, flames?

Jay Soffian (3):
  remote: refactor some logic into get_stale_heads()
  builtin-fetch: add --dry-run option
  builtin-fetch: add --prune option

 builtin-fetch.c  |   30 +++++++++++++++++++++++++++---
 builtin-remote.c |   32 ++++++++------------------------
 remote.c         |   40 ++++++++++++++++++++++++++++++++++++++++
 remote.h         |    3 +++
 4 files changed, 78 insertions(+), 27 deletions(-)

^ permalink raw reply

* [PATCH/RFC 1/3] remote: refactor some logic into get_stale_heads()
From: Jay Soffian @ 2009-11-06  5:10 UTC (permalink / raw)
  To: git; +Cc: Jay Soffian
In-Reply-To: <1257484241-27219-1-git-send-email-jaysoffian@gmail.com>

Move the logic in builtin-remote.c which determines which local heads are stale
to remote.c so it can be used by other builtins.
---
 builtin-remote.c |   32 ++++++++------------------------
 remote.c         |   40 ++++++++++++++++++++++++++++++++++++++++
 remote.h         |    3 +++
 3 files changed, 51 insertions(+), 24 deletions(-)

diff --git a/builtin-remote.c b/builtin-remote.c
index 0777dd7..b48267b 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -227,32 +227,10 @@ struct ref_states {
 	int queried;
 };
 
-static int handle_one_branch(const char *refname,
-	const unsigned char *sha1, int flags, void *cb_data)
-{
-	struct ref_states *states = cb_data;
-	struct refspec refspec;
-
-	memset(&refspec, 0, sizeof(refspec));
-	refspec.dst = (char *)refname;
-	if (!remote_find_tracking(states->remote, &refspec)) {
-		struct string_list_item *item;
-		const char *name = abbrev_branch(refspec.src);
-		/* symbolic refs pointing nowhere were handled already */
-		if ((flags & REF_ISSYMREF) ||
-		    string_list_has_string(&states->tracked, name) ||
-		    string_list_has_string(&states->new, name))
-			return 0;
-		item = string_list_append(name, &states->stale);
-		item->util = xstrdup(refname);
-	}
-	return 0;
-}
-
 static int get_ref_states(const struct ref *remote_refs, struct ref_states *states)
 {
 	struct ref *fetch_map = NULL, **tail = &fetch_map;
-	struct ref *ref;
+	struct ref *ref, *stale_refs;
 	int i;
 
 	for (i = 0; i < states->remote->fetch_refspec_nr; i++)
@@ -268,11 +246,17 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
 		else
 			string_list_append(abbrev_branch(ref->name), &states->tracked);
 	}
+	stale_refs = get_stale_heads(states->remote, fetch_map);
+	for (ref = stale_refs; ref; ref = ref->next) {
+		struct string_list_item *item =
+			string_list_append(abbrev_branch(ref->name), &states->stale);
+		item->util = xstrdup(ref->name);
+	}
+	free_refs(stale_refs);
 	free_refs(fetch_map);
 
 	sort_string_list(&states->new);
 	sort_string_list(&states->tracked);
-	for_each_ref(handle_one_branch, states);
 	sort_string_list(&states->stale);
 
 	return 0;
diff --git a/remote.c b/remote.c
index 73d33f2..ee48b49 100644
--- a/remote.c
+++ b/remote.c
@@ -6,6 +6,7 @@
 #include "revision.h"
 #include "dir.h"
 #include "tag.h"
+#include "string-list.h"
 
 static struct refspec s_tag_refspec = {
 	0,
@@ -1586,3 +1587,42 @@ struct ref *guess_remote_head(const struct ref *head,
 
 	return list;
 }
+
+struct stale_heads_info {
+	struct remote *remote;
+	struct string_list *ref_names;
+	struct ref **stale_refs_tail;
+};
+
+static int get_stale_heads_cb(const char *refname,
+	const unsigned char *sha1, int flags, void *cb_data)
+{
+	struct stale_heads_info *info = cb_data;
+	struct refspec refspec;
+	memset(&refspec, 0, sizeof(refspec));
+	refspec.dst = (char *)refname;
+	if (!remote_find_tracking(info->remote, &refspec)) {
+		if (!((flags & REF_ISSYMREF) ||
+		    string_list_has_string(info->ref_names, refspec.src))) {
+			struct ref *ref = make_linked_ref(refname, &info->stale_refs_tail);
+			hashcpy(ref->new_sha1, sha1);
+		}
+	}
+	return 0;
+}
+
+struct ref *get_stale_heads(struct remote *remote, struct ref *fetch_map)
+{
+	struct ref *ref, *stale_refs = NULL;
+	struct string_list ref_names = { NULL, 0, 0, 0 };
+	struct stale_heads_info info;
+	info.remote = remote;
+	info.ref_names = &ref_names;
+	info.stale_refs_tail = &stale_refs;
+	for (ref = fetch_map; ref; ref = ref->next)
+		string_list_append(ref->name, &ref_names);
+	sort_string_list(&ref_names);
+	for_each_ref(get_stale_heads_cb, &info);
+	string_list_clear(&ref_names, 0);
+	return stale_refs;
+}
diff --git a/remote.h b/remote.h
index 5db8420..d0aba81 100644
--- a/remote.h
+++ b/remote.h
@@ -154,4 +154,7 @@ struct ref *guess_remote_head(const struct ref *head,
 			      const struct ref *refs,
 			      int all);
 
+/* Return refs which no longer exist on remote */
+struct ref *get_stale_heads(struct remote *remote, struct ref *fetch_map);
+
 #endif
-- 
1.6.4.2

^ permalink raw reply related

* [PATCH/RFC 2/3] builtin-fetch: add --dry-run option
From: Jay Soffian @ 2009-11-06  5:10 UTC (permalink / raw)
  To: git; +Cc: Jay Soffian
In-Reply-To: <1257484241-27219-2-git-send-email-jaysoffian@gmail.com>

Teach fetch --dry-run. Unfortunately OPT__DRY_RUN() cannot be used as fetch
already uses "-n" for something else.
---
 builtin-fetch.c |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/builtin-fetch.c b/builtin-fetch.c
index cb48c57..985b36b 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -23,7 +23,7 @@ enum {
 	TAGS_SET = 2
 };
 
-static int append, force, keep, update_head_ok, verbosity;
+static int append, dry_run, force, keep, update_head_ok, verbosity;
 static int tags = TAGS_DEFAULT;
 static const char *depth;
 static const char *upload_pack;
@@ -42,6 +42,8 @@ static struct option builtin_fetch_options[] = {
 		    "fetch all tags and associated objects", TAGS_SET),
 	OPT_SET_INT('n', NULL, &tags,
 		    "do not fetch all tags (--no-tags)", TAGS_UNSET),
+	OPT_BOOLEAN(0, "dry-run", &dry_run,
+		    "dry run"),
 	OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
 	OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
 		    "allow updating of HEAD ref"),
@@ -178,6 +180,8 @@ static int s_update_ref(const char *action,
 	char *rla = getenv("GIT_REFLOG_ACTION");
 	static struct ref_lock *lock;
 
+	if (dry_run)
+		return 0;
 	if (!rla)
 		rla = default_rla.buf;
 	snprintf(msg, sizeof(msg), "%s: %s", rla, action);
@@ -303,7 +307,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
 	char note[1024];
 	const char *what, *kind;
 	struct ref *rm;
-	char *url, *filename = git_path("FETCH_HEAD");
+	char *url, *filename = dry_run ? "/dev/null" : git_path("FETCH_HEAD");
 
 	fp = fopen(filename, "a");
 	if (!fp)
@@ -586,7 +590,7 @@ static int do_fetch(struct transport *transport,
 		die("Don't know how to fetch from %s", transport->url);
 
 	/* if not appending, truncate FETCH_HEAD */
-	if (!append) {
+	if (!append && !dry_run) {
 		char *filename = git_path("FETCH_HEAD");
 		FILE *fp = fopen(filename, "w");
 		if (!fp)
-- 
1.6.4.2

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox