* [PATCH 4/4] xdl_merge(): fix thinko
From: Johannes Schindelin @ 2006-11-29 23:25 UTC (permalink / raw)
To: Davide Libenzi, git; +Cc: junkio
If one side's block (of changed lines) ends later than the other
side's block, the former should be tested against the next block
of the other side, not vice versa.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
xdiff/xmerge.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/xdiff/xmerge.c b/xdiff/xmerge.c
index 9fe2059..6d4f9b6 100644
--- a/xdiff/xmerge.c
+++ b/xdiff/xmerge.c
@@ -318,13 +318,13 @@ static int xdl_do_merge(xdfenv_t *xe1, x
xscr1->i1 = i2;
xscr1->i2 += xscr1->chg2;
xscr1->chg2 = 0;
- xscr1 = xscr1->next;
+ xscr2 = xscr2->next;
} else if (i2 > i1) {
xscr2->chg1 -= i2 - i1;
xscr2->i1 = i1;
xscr2->i2 += xscr2->chg2;
xscr2->chg2 = 0;
- xscr2 = xscr2->next;
+ xscr1 = xscr1->next;
} else {
xscr1 = xscr1->next;
xscr2 = xscr2->next;
--
1.4.4.g5aac-dirty
^ permalink raw reply related
* Re: [PATCH 2/2] Don't require config file for "stg mail"
From: Pavel Roskin @ 2006-11-29 23:27 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git
In-Reply-To: <b0943d9e0611290829h291942d7x13247511d16afeee@mail.gmail.com>
Hello, Catalin!
On Wed, 2006-11-29 at 16:29 +0000, Catalin Marinas wrote:
> On 29/11/06, Pavel Roskin <proski@gnu.org> wrote:
> > When calculating the string to be used in the From: field, don't require
> > it to come from the configuration file. Instead, reuse already known
> > authname and authemail values as the default. They can be taken from
> > the GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL environment variables.
>
> Your patch uses the author of the patch which can be different from
> the person sending the e-mail. It could indeed use the author from GIT
> variables or configuration (not the patch author) and I already have a
> patch from Karl Hasselström for this (which I haven't found the time
> to check properly).
The funny thing it, GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL are only used
in the code to determine the author of the patch.
Apparently, things are more twisted than I expected, so they need some
untangling first.
> Once I merge Karl's patch, I'll modify StGIT to use the GIT defaults
> if there is no sender configured.
Sounds good.
--
Regards,
Pavel Roskin
^ permalink raw reply
* Re: [PATCH 0/2] Making "git commit" to mean "git commit -a".
From: Carl Worth @ 2006-11-29 23:37 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Nicolas Pitre, git
In-Reply-To: <7vr6vmsnly.fsf@assigned-by-dhcp.cox.net>
[-- Attachment #1: Type: text/plain, Size: 8447 bytes --]
On Tue, 28 Nov 2006 23:44:57 -0800, Junio C Hamano wrote:
> Nicolas Pitre <nico@cam.org> writes:
>
> > This argument has its converse. What you should _not_ have to worry
> > about all the time is whether your index really includes all the changes
> > you want included in your next commit.
>
> That's what we have "git diff" with various output options for;
> I often do "git diff --stat" or "git diff --name-status" when I
> know I am about to commit in a dirty working tree. I suspect
> that I am not getting your point.
I think you just backed up the point you didn't understand. You said,
"when I know I am about to commit in a dirty working tree". That's an
exceptional thing to do, (from the point of view of your "pure
discipline"), so you will always be conscious of doing it when you do.
> > And whether wanting to leave local changes in the working directory
> > without commiting them actually happen more often than wanting to commit
> > every changes is arguable.
>
> I do not think anybody is talking about which happens more
> often.
That's exactly what I'm trying to talk about here.
I've been using your "commit -i and -a as default" patches since you
sent them out, (thanks again for sending them). I will readily admit
that the very first commit I wanted to make was a "partial, dirty
tree" commit.
What happened was that I had made a couple of independent changes in
concert and now I wanted to commit them separately. I think that in my
usage, this is the most common case for me using update-index and
commit rather than "commit -a". It also happened that the independent
changes modified disjoint sets of files.
Now, the index works perfectly for this kind of situation, and I like
it. Some of the people that I know, (people who are currently refusing
to touch git, and people for whom I've been trying to be a proponent
in this discussion), would just use "git commit file1 file2 ...." in
this situation. I don't do that since I really like being able to
identify the files in one command, (update-index), and then preview
the commit I'm going to make before I do so, (with "diff
--cached). Sure, I could just do the commit, do an after-the-fact
review with "show" and then reset if I screwed up, but that just feels
like the wrong way to go about it.
So, I'm an index lover here. I see how it's useful and I use it on a
regular basis. But I do believe I make "clean index" commits more
frequently. And regardless, I still think we should change the default
for git-commit to make it easier for users to learn git.
[As an aside, the situation of independent changes being mixed in a
working tree is not always so lucky as to be cleanly separated into
disjoint file sets. When it's not, I have to disentangle them. Now,
the index could really help during this operation too, but we would
need better tools than update-index which only works on a per-file
basis. Something that let me easily select chunks of the patch would
be really nice.]
> "screw the index" people do not have to worry about the
> index during the course of their changes in the working tree
> toward the next commit, and the only time they need to tell git
> (which _IS_ a system based on the index, dammit)
I don't think "screw the index" is an accurate way to characterize my
position at least. [In fact is "_the_ index" even a good way to
describe what git has? Doesn't a commit operation that lists explicit
files build up an alternate index which it will throw away if there's
a failure at some point?]
So some git operations work by creating a tree object by first putting
some state into an index file. That's fine. And users can even take
advantage of doing that themselves if they want to. That's fine too.
All I'd like is that new users didn't have to learn those concepts as
early as they have to do with current git.
Now, one time git really does have "_the_ index" and when the user
really needs to know about it is when there is a conflicted merge. As
Linus has been pointing out recently, there are some important
benefits that the index provides at this point. And I think this is
the right time to teach users about the index. I think they can learn
it and take advantage of it at that point, (and I wouldn't even expect
them to necessarily want to change the configuration of what "git
commit" means).
In general, the process of resolving a conflicted merge is poorly
presented to the user by git. The commands that leave the conflicted
index, (git pull, git rebase, etc.) and that examine it, (git status),
don't do a good job of telling the user what to do (git update-index)
and how to examine the situation (git diff --merge). I think this
could be improved a lot, and one piece of that is the "git resolve"
thing I've been proposing recently.
> It might make sense to have a configuration in .git/config that
> says "user.workingtreeistheking = true". This should obviously
> affect what "git commit" does by default,
I'd love to see a configuration value added, but I don't think we gain
anything at all if we add a configuration value and leave the default
value the same. It's not easier to tell new users to configure git to
work this way then it is to tell them to use "commit -a".
> but it also should
> change the behaviour of other commands to suit the "screw the
> index" workflow better.
>
> For example, the configuration should probably make "git diff"
> (without an explicit --cached nor HEAD) pretend it was asked to
> show diff between HEAD and the working tree, because the user
> chose not to care about the index.
Actually, I strongly disagree on this point. Months ago, before I
understood the index as well as I do now, I did argue for a change
like that, since I thought the index was just confusing. But I think
it would be a mistake to make two fundamentally different models creep
through all the tools. (Which is to say, I'm agreeing with what I
think your motivation is for pushing back against that kind of thing.)
Plus, this model would be just broken anyway. The problem is that "git
diff" meaning "git diff HEAD" works just fine when you're in a
"normal" situation. But as soon as you're looking at a conflicted
merge, then "git diff HEAD" isn't useful at all, but the difference
between the index and the working tree is very useful. In that
situation, the behavior of "git diff" suddenly makes a lot of sense,
and the index has its chance to shine. This can lead to a nice
epiphany for users I think.
Not caring about the index
> is different from consciously keeping the index clean;
Yes, those are different. And I agree with you that a "pretend the
index doesn't exist" mode would not be an improvement.
What I would like to see instead is that all commands keep the index
clean by default, (with the notable exception of failed merge). And
the only way to get it dirty would be with an explicit option such as
"apply --index".
See? If users only get a dirty index by asking for it, then the
likelihood of confusion goes way down, as users who haven't heard of
"the index" certainly won't have any reason to pass a "--index" option
around.
> Would that make people happy? I do not think so. I think it
> will lead to more confusion to have two majorly different
> semantics in the same set of tools.
Agreed. Let's not go there.
I think what I'm asking for is a much more mild change. The "keep the
index clean" behavior exists almost everywhere already, (the few
exceptions are things like "git cherry-pick -n", and the notable
exception of a conflicted merge). So I don't think supporting "commit
-a by default" means we have to introduce a large conceptual change.
Also, for the case of the conflicted merge, the index really is a key
part of what lets the user work through things. But there's really not
an _essential_ need for the user to fully grok the index to take
advantage of that. It's not hard to describe the behavior of "git
diff" and "git diff --merge" in terms of things that the user wants to
know, without mentioning the index at all. (Now, if a user asks, "how
is git able to tell me all this amazing stuff", then would be a great
time to explain the index, I think).
Did I succeed in getting you to consider anything new here? I hope
so. I don't want you to feel like we're both just saying the same
things back and forth over and over with no progress.
-Carl
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 0/2] Making "git commit" to mean "git commit -a".
From: Johannes Schindelin @ 2006-11-29 23:53 UTC (permalink / raw)
To: Carl Worth; +Cc: Junio C Hamano, Nicolas Pitre, git
In-Reply-To: <87ejrlvn7r.wl%cworth@cworth.org>
Hi,
On Wed, 29 Nov 2006, Carl Worth wrote:
> [As an aside, the situation of independent changes being mixed in a
> working tree is not always so lucky as to be cleanly separated into
> disjoint file sets. When it's not, I have to disentangle them. Now, the
> index could really help during this operation too, but we would need
> better tools than update-index which only works on a per-file basis.
> Something that let me easily select chunks of the patch would be really
> nice.]
I regularly do something like
$ git diff [file] > a1.patch
$ vi a1.patch
[edit out the chunks I want to commit]
$ git apply -R < a1.patch
$ git commit [file]
$ git apply < a1.patch
Seems a little bit convoluted, but works...
Hth,
Dscho
^ permalink raw reply
* Handling of branches in stgit
From: Yann Dirson @ 2006-11-30 0:00 UTC (permalink / raw)
To: Catalin Marinas; +Cc: GIT list
I have started to work on recording parent information for stgit
branches, so we don't need to give the same info on every "git pull".
I'm facing a problem, in that we have several kind of stgit branches:
* those created against a cogito branch (eg. by "cg clone" and "stg
init"). They work pretty much intuitively (and it happens I mostly
used this flavour before those tests). All we need is the name of
the local branch, and "stg pull <branch>" relies on "git fetch" to
find the repository information in .git/branches/<branch>.
In this case, it is easy to request pulling from any branch, but
usually only one of them is what you want, and the results of using
another one (or forgetting to specify the one you want) can be
annoying [ISSUE 1]. Hence this work of mine: being able to store
this info in .git/patches/<stack>/parent (my initial implementation)
was sufficient in theory.
But "stg pull" allows for a refspec argument. Since the branch
mapping is already defined in a file, and I canno think of any
useful way to override it, maybe we could make sure noone uses it in
such a case ?
* but those created against a local branch are typically different,
and updated by "stg pull . <branch>". In that case, we have to
specify the repository (".") explicitely, in addition to the branch,
and the way to use the use them is different.
* and it gets better with those branches created against a git remote
branch (eg. by "stg clone" or "stg branch -c" against an existing
remote branch), typically updated via "stg pull <remote>", where the
repo information is extracted by "git fetch" from
.git/remotes/<remote>. That is, we do not specify a branch or a
repository URL, but an alias that may cover several branches from
another repo.
Here the branch information from the remotes file appears not to be
used at all (in fact all branches are fetched - not sure that it's
always what we want, but I'll wait to find myself limited by this
behaviour before complaining ;)
Also, "stgit pull <remote>" using "git pull" by default, it is the
1st branch listed in the remotes file that gets taken as parent
[ISSUE 2]. We should probably instead run "git fetch <remote>" and
then then "git pull . <branch>", but that surely requires some
changes to the "stg pull" internals.
Thus (modulo that issue), we need 2 infos: "remote" and branch.
Storing the latter should help to solve issue 2.
Note: whereas "stg pull origin", while pulling a "foo" branch, cannot
know current "foo2" branch should be rebased to "foo", (after renaming
remotes/origin to foo) "stg pull foo", not only fetches "origin" as
expected, but also (seemingly correctly but hell how does it know
[ISSUE 3]) rebases current "master" to "origin" - is "master"
special in any way here ? I did not find anything about this in the
source, although I found a handful of occurences of "master" in
commands/branch.py, which seem to imply "master" is so special it
cannot be deleted, which would look like abuse to me [ISSUE 4].
Now what do we do next ?
We could implement an ad-hoc solution acknowledging there are 3
different ways to work with a branch, keeping the current "stg pull"
syntaxes (they are already a pain for users IMHO) and storing
paremeters as ad-hoc values, or we could try to rework the "stg pull"
command line.
Some of my ideas for the latter include:
- store a "parent branch" with the name of the parent branch in the
local repository
- store a "parent repository" (ie. "." for local branches, "AUTO" for
cogito branches, and <remote> for git branches)
- rejecting non-default arguments and adding new options to allow to
specify/store alternative values
- we'll need to make sure there are no remote branches of one type
shadowed by one of the other type with same name, and do some sanity
checks that specified branch in a given remote really exists.
How does that sound ?
--
^ permalink raw reply
* Re: git and bzr
From: Carl Worth @ 2006-11-30 0:05 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Marko Macek, git, bazaar-ng
In-Reply-To: <Pine.LNX.4.64.0611291235590.3513@woody.osdl.org>
[-- Attachment #1: Type: text/plain, Size: 2851 bytes --]
On Wed, 29 Nov 2006 12:45:18 -0800 (PST), Linus Torvalds wrote:
>
> Nothing forces you to change the index. None of the normal operations do
> that, for example, and you really have to _explicitly_ ask git to update
> the index for you.
Yes, this is goog.
> Why? I mean really.. Why do people mind the index? If you've not done
> anything to explicitly update it, and you just write "git commit", it will
> tell you exactly which files are dirty, which files are untracked, and
> then say "nothing to commit".
To start with, that message confuses a lot of new users. "What do you
mean there's nothing to commit? I just made changes. And I know you
noticed them because you just mentioned the names of the files with
the changes to me!".
So at the very least, there's some missing guidance as to how to get
from the "nothing to commit" stage to actually commit the files the
user was trying to commit when they typed "git commit" in the first
place.
> Maybe we shouldn't even say "use git-update-index to mark for commit", we
> should just say "use 'git commit -a' to mark for commit",
Yes, I submitted a patch for this. I don't think Junio picked it up
because it got him thinking about all the other situations where "git
status" doesn't give as much guidance as it should
Even with that, the user has to go through the process of:
git commit
"hmm... why didn't that work"
read message
git commit -a
That's not a _huge_ problem, but it is a little road-bump that a lot of
people meet on their first attempt at git. In the thread on the fedora
mailing list that prompted my first "user-interface warts" and the
patch I mentioned above, the process was worse:
git commit
"hmm... why didn't that work"
read message
git update-index
git commit
"crap... it still didn't work even when I did what it told me to do"
Here's the original version of that report:
https://www.redhat.com/archives/fedora-maintainers/2006-November/msg00141.html
> And the ADVANTAGES of the index are legion. You may not appreciate them
> initially, but the disadvantages people talk about really don't exist in
> real life, and once you actually start doing merges with conflicts, and
> fix things up one file at a time (and perhaps take a break and do
> something else before you come back to the rest of the conflicts), the
> index saves your sorry ass, and is a _huge_ advantage.
In none of these recent threads have I been arguing disadvantages of
the index. I'm really just trying to remove one small hurdle that
does trip up new users, (see above). I'm not trying to introduce any
large conceptual change into how git works, nor even what experienced
users do.
> So get over your fears, and just ignore it, and things will be fine.
Let's help people do exactly that by making the behavior of "git
commit -a" be the default for "git commit".
-Carl
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: git and bzr
From: Carl Worth @ 2006-11-30 0:08 UTC (permalink / raw)
To: Linus Torvalds; +Cc: bazaar-ng, Marko Macek, git
In-Reply-To: <87bqmpvlxf.wl%cworth@cworth.org>
[-- Attachment #1: Type: text/plain, Size: 431 bytes --]
On Wed, 29 Nov 2006 16:05:16 -0800, Carl Worth wrote:
> On Wed, 29 Nov 2006 12:45:18 -0800 (PST), Linus Torvalds wrote:
> >
> > Nothing forces you to change the index. None of the normal operations do
> > that, for example, and you really have to _explicitly_ ask git to update
> > the index for you.
>
> Yes, this is goog.
I meant "good" there for anyone confused, (I'm not sure how that
slipped passed my spell-checker).
-Carl
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 0/3] Misc stgit patches
From: Yann Dirson @ 2006-11-30 0:23 UTC (permalink / raw)
To: Catalin Marinas; +Cc: GIT list
One of the following patches contains a pretty substantial change to stack.py to help
adding new stored properties to a Series just like it is done for a Patch. It was
expected to be the first in a series for storing branch parent information, but as you
may have read already, it's not for today :)
--
Yann Dirson <ydirson@altern.org> |
Debian-related: <dirson@debian.org> | Support Debian GNU/Linux:
| Freedom, Power, Stability, Gratis
^ permalink raw reply
* [PATCH 2/3] More config examples.
From: Yann Dirson @ 2006-11-30 0:27 UTC (permalink / raw)
To: Catalin Marinas; +Cc: GIT list
In-Reply-To: <20061130002304.21981.67797.stgit@gandelf.nowhere.earth>
Signed-off-by: Yann Dirson <ydirson@altern.org>
---
examples/stgitrc | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/examples/stgitrc b/examples/stgitrc
index cc6e910..9ed2988 100644
--- a/examples/stgitrc
+++ b/examples/stgitrc
@@ -32,6 +32,7 @@
# this value overrides the default PAGER environment variable
#pager: ~/share/stgit/contrib/diffcol.sh
+#pager: filterdiff --annotate | colordiff | less -FRX
# GIT pull command (should take the same arguments as git-pull)
^ permalink raw reply related
* [PATCH 1/3] Document some current bugs and add to the TODO list.
From: Yann Dirson @ 2006-11-30 0:27 UTC (permalink / raw)
To: Catalin Marinas; +Cc: GIT list
In-Reply-To: <20061130002304.21981.67797.stgit@gandelf.nowhere.earth>
Signed-off-by: Yann Dirson <ydirson@altern.org>
---
TODO | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/TODO b/TODO
index 6f7a132..ad02a0e 100644
--- a/TODO
+++ b/TODO
@@ -26,3 +26,54 @@ The future, when time allows or if someone else does them:
- patch synchronisation between between branches (as some people,
including me have the same patches based on different branches and
they have scripts for moving the changes in one to the others)
+- numeric shortcuts for naming patches near top (eg. +1, -2)
+- (config?) parameter for number of patches included by "series -s"
+- refuse to "stg init" a branch known as remote (through .git/remotes/,
+ .git/branches/ or any other info)
+
+Bugs:
+
+- cannot use "stg refresh file" after "cg-rm file"
+- patch names with spaces are accepted by "stg new" but break "stg series -d"
+- "stg goto $(stg top)" fails with unhandled exception
+- at least "commit is not robust wrt out-of-diskspace condition:
+|deps$ stg commit
+|error: git-checkout-index: unable to write file MANIFEST
+|error: git-checkout-index: unable to write file META.yml
+|error: git-checkout-index: unable to write file Makefile.PL
+|error: git-checkout-index: unable to write file doc/README.dbk.xml
+|error: git-checkout-index: unable to write file graph-includes
+|error: git-checkout-index: unable to write file lib/graphincludes/params.pm
+|fatal: unable to write new index file
+|stg commit: git-read-tree failed (local changes maybe?)
+|Committing 4 patches...
+(luckily nothing was really committed)
+
+- cannot branch off arbitrary branch when current branch not under
+stgit control:
+|$ stg branch
+|bar
+|$ stg branch -c foo2 foo
+|stg branch: Branch "bar" not initialised
+
+- patch created with empty description ("stg new" and quit editor
+without saving) confuse "series -d":
+|$ stg series -ds
+|+ p5 | p5
+|Traceback (most recent call last):
+| File "/usr/bin/stg", line 43, in ?
+| main()
+| File "/var/lib/python-support/python2.4/stgit/main.py", line 261, in main
+| command.func(parser, options, args)
+| File "/var/lib/python-support/python2.4/stgit/commands/series.py", line 107, in func
+| __print_patch(applied[-1], '> ', '0>', max_len, options)
+| File "/var/lib/python-support/python2.4/stgit/commands/series.py", line 63, in __print_patch
+| print prefix + patch.ljust(length) + ' | ' + __get_description(patch)
+| File "/var/lib/python-support/python2.4/stgit/commands/series.py", line 55, in __get_description
+| descr = p.get_description().strip()
+|AttributeError: 'NoneType' object has no attribute 'strip'
+|dwitch@gandelf:/export/work/yann/git/foo/a$ stg series
+|+ p5
+|> y
+|$ cat .git/patches/master/patches/y/description
^ permalink raw reply related
* [PATCH 3/3] Create a StgitObject class to factorise code for property handling.
From: Yann Dirson @ 2006-11-30 0:27 UTC (permalink / raw)
To: Catalin Marinas; +Cc: GIT list
In-Reply-To: <20061130002304.21981.67797.stgit@gandelf.nowhere.earth>
This change makes it easier to add new stored fields to the Series object,
without having to duplicate existing code from Patch.
Generic field accessors were taken from the Patch class. Dir accessors
were added to avoid making the __dir attribute public, and were used
to replace Series::__series_dir (that name was a bit redundant anyway).
Create_empty_field came as a natural addition to factorise more code.
Signed-off-by: Yann Dirson <ydirson@altern.org>
---
stgit/stack.py | 198 +++++++++++++++++++++++++++++---------------------------
1 files changed, 103 insertions(+), 95 deletions(-)
diff --git a/stgit/stack.py b/stgit/stack.py
index 8fa3846..8cd632e 100644
--- a/stgit/stack.py
+++ b/stgit/stack.py
@@ -119,27 +119,58 @@ def edit_file(series, line, comment, show_patch = True):
# Classes
#
-class Patch:
+class StgitObject:
+ """An object with stgit-like properties stored as files in a directory
+ """
+ def _set_dir(self, dir):
+ self.__dir = dir
+ def dir(self):
+ return self.__dir
+
+ def create_empty_field(self, name):
+ print "Creating '%s'" % os.path.join(self.__dir, name)
+ create_empty_file(os.path.join(self.__dir, name))
+
+ def _get_field(self, name, multiline = False):
+ id_file = os.path.join(self.__dir, name)
+ if os.path.isfile(id_file):
+ line = read_string(id_file, multiline)
+ if line == '':
+ return None
+ else:
+ return line
+ else:
+ return None
+
+ def _set_field(self, name, value, multiline = False):
+ fname = os.path.join(self.__dir, name)
+ if value and value != '':
+ write_string(fname, value, multiline)
+ elif os.path.isfile(fname):
+ os.remove(fname)
+
+
+class Patch(StgitObject):
"""Basic patch implementation
"""
def __init__(self, name, series_dir, refs_dir):
self.__series_dir = series_dir
self.__name = name
- self.__dir = os.path.join(self.__series_dir, self.__name)
+ self._set_dir(os.path.join(self.__series_dir, self.__name))
self.__refs_dir = refs_dir
self.__top_ref_file = os.path.join(self.__refs_dir, self.__name)
self.__log_ref_file = os.path.join(self.__refs_dir,
self.__name + '.log')
def create(self):
- os.mkdir(self.__dir)
- create_empty_file(os.path.join(self.__dir, 'bottom'))
- create_empty_file(os.path.join(self.__dir, 'top'))
+ os.mkdir(self.dir())
+ self.create_empty_field('bottom')
+ self.create_empty_field('top')
def delete(self):
- for f in os.listdir(self.__dir):
- os.remove(os.path.join(self.__dir, f))
- os.rmdir(self.__dir)
+ for f in os.listdir(self.dir()):
+ os.remove(os.path.join(self.dir(), f))
+ os.rmdir(self.dir())
os.remove(self.__top_ref_file)
if os.path.exists(self.__log_ref_file):
os.remove(self.__log_ref_file)
@@ -148,16 +179,16 @@ class Patch:
return self.__name
def rename(self, newname):
- olddir = self.__dir
+ olddir = self.dir()
old_top_ref_file = self.__top_ref_file
old_log_ref_file = self.__log_ref_file
self.__name = newname
- self.__dir = os.path.join(self.__series_dir, self.__name)
+ self._set_dir(os.path.join(self.__series_dir, self.__name))
self.__top_ref_file = os.path.join(self.__refs_dir, self.__name)
self.__log_ref_file = os.path.join(self.__refs_dir,
self.__name + '.log')
- os.rename(olddir, self.__dir)
+ os.rename(olddir, self.dir())
os.rename(old_top_ref_file, self.__top_ref_file)
if os.path.exists(old_log_ref_file):
os.rename(old_log_ref_file, self.__log_ref_file)
@@ -173,69 +204,51 @@ class Patch:
if top:
self.__update_top_ref(top)
- def __get_field(self, name, multiline = False):
- id_file = os.path.join(self.__dir, name)
- if os.path.isfile(id_file):
- line = read_string(id_file, multiline)
- if line == '':
- return None
- else:
- return line
- else:
- return None
-
- def __set_field(self, name, value, multiline = False):
- fname = os.path.join(self.__dir, name)
- if value and value != '':
- write_string(fname, value, multiline)
- elif os.path.isfile(fname):
- os.remove(fname)
-
def get_old_bottom(self):
- return self.__get_field('bottom.old')
+ return self._get_field('bottom.old')
def get_bottom(self):
- return self.__get_field('bottom')
+ return self._get_field('bottom')
def set_bottom(self, value, backup = False):
if backup:
- curr = self.__get_field('bottom')
- self.__set_field('bottom.old', curr)
- self.__set_field('bottom', value)
+ curr = self._get_field('bottom')
+ self._set_field('bottom.old', curr)
+ self._set_field('bottom', value)
def get_old_top(self):
- return self.__get_field('top.old')
+ return self._get_field('top.old')
def get_top(self):
- return self.__get_field('top')
+ return self._get_field('top')
def set_top(self, value, backup = False):
if backup:
- curr = self.__get_field('top')
- self.__set_field('top.old', curr)
- self.__set_field('top', value)
+ curr = self._get_field('top')
+ self._set_field('top.old', curr)
+ self._set_field('top', value)
self.__update_top_ref(value)
def restore_old_boundaries(self):
- bottom = self.__get_field('bottom.old')
- top = self.__get_field('top.old')
+ bottom = self._get_field('bottom.old')
+ top = self._get_field('top.old')
if top and bottom:
- self.__set_field('bottom', bottom)
- self.__set_field('top', top)
+ self._set_field('bottom', bottom)
+ self._set_field('top', top)
self.__update_top_ref(top)
return True
else:
return False
def get_description(self):
- return self.__get_field('description', True)
+ return self._get_field('description', True)
def set_description(self, line):
- self.__set_field('description', line, True)
+ self._set_field('description', line, True)
def get_authname(self):
- return self.__get_field('authname')
+ return self._get_field('authname')
def set_authname(self, name):
if not name:
@@ -243,10 +256,10 @@ class Patch:
name = config.get('stgit', 'authname')
elif 'GIT_AUTHOR_NAME' in os.environ:
name = os.environ['GIT_AUTHOR_NAME']
- self.__set_field('authname', name)
+ self._set_field('authname', name)
def get_authemail(self):
- return self.__get_field('authemail')
+ return self._get_field('authemail')
def set_authemail(self, address):
if not address:
@@ -254,18 +267,18 @@ class Patch:
address = config.get('stgit', 'authemail')
elif 'GIT_AUTHOR_EMAIL' in os.environ:
address = os.environ['GIT_AUTHOR_EMAIL']
- self.__set_field('authemail', address)
+ self._set_field('authemail', address)
def get_authdate(self):
- return self.__get_field('authdate')
+ return self._get_field('authdate')
def set_authdate(self, date):
if not date and 'GIT_AUTHOR_DATE' in os.environ:
date = os.environ['GIT_AUTHOR_DATE']
- self.__set_field('authdate', date)
+ self._set_field('authdate', date)
def get_commname(self):
- return self.__get_field('commname')
+ return self._get_field('commname')
def set_commname(self, name):
if not name:
@@ -273,10 +286,10 @@ class Patch:
name = config.get('stgit', 'commname')
elif 'GIT_COMMITTER_NAME' in os.environ:
name = os.environ['GIT_COMMITTER_NAME']
- self.__set_field('commname', name)
+ self._set_field('commname', name)
def get_commemail(self):
- return self.__get_field('commemail')
+ return self._get_field('commemail')
def set_commemail(self, address):
if not address:
@@ -284,17 +297,17 @@ class Patch:
address = config.get('stgit', 'commemail')
elif 'GIT_COMMITTER_EMAIL' in os.environ:
address = os.environ['GIT_COMMITTER_EMAIL']
- self.__set_field('commemail', address)
+ self._set_field('commemail', address)
def get_log(self):
- return self.__get_field('log')
+ return self._get_field('log')
def set_log(self, value, backup = False):
- self.__set_field('log', value)
+ self._set_field('log', value)
self.__update_log_ref(value)
-class Series:
+class Series(StgitObject):
"""Class including the operations on series
"""
def __init__(self, name = None):
@@ -309,22 +322,21 @@ class Series:
except git.GitException, ex:
raise StackException, 'GIT tree not initialised: %s' % ex
- self.__series_dir = os.path.join(self.__base_dir, 'patches',
- self.__name)
+ self._set_dir(os.path.join(self.__base_dir, 'patches', self.__name))
self.__refs_dir = os.path.join(self.__base_dir, 'refs', 'patches',
self.__name)
self.__base_file = os.path.join(self.__base_dir, 'refs', 'bases',
self.__name)
- self.__applied_file = os.path.join(self.__series_dir, 'applied')
- self.__unapplied_file = os.path.join(self.__series_dir, 'unapplied')
- self.__current_file = os.path.join(self.__series_dir, 'current')
- self.__descr_file = os.path.join(self.__series_dir, 'description')
+ self.__applied_file = os.path.join(self.dir(), 'applied')
+ self.__unapplied_file = os.path.join(self.dir(), 'unapplied')
+ self.__current_file = os.path.join(self.dir(), 'current')
+ self.__descr_file = os.path.join(self.dir(), 'description')
# where this series keeps its patches
- self.__patch_dir = os.path.join(self.__series_dir, 'patches')
+ self.__patch_dir = os.path.join(self.dir(), 'patches')
if not os.path.isdir(self.__patch_dir):
- self.__patch_dir = self.__series_dir
+ self.__patch_dir = self.dir()
# if no __refs_dir, create and populate it (upgrade old repositories)
if self.is_initialised() and not os.path.isdir(self.__refs_dir):
@@ -333,7 +345,7 @@ class Series:
self.get_patch(patch).update_top_ref()
# trash directory
- self.__trash_dir = os.path.join(self.__series_dir, 'trash')
+ self.__trash_dir = os.path.join(self.dir(), 'trash')
if self.is_initialised() and not os.path.isdir(self.__trash_dir):
os.makedirs(self.__trash_dir)
@@ -345,10 +357,7 @@ class Series:
def __set_current(self, name):
"""Sets the topmost patch
"""
- if name:
- write_string(self.__current_file, name)
- else:
- create_empty_file(self.__current_file)
+ self._set_field('current', name)
def get_patch(self, name):
"""Return a Patch object for the given name
@@ -366,10 +375,7 @@ class Series:
def get_current(self):
"""Return the name of the topmost patch, or None if there is
no such patch."""
- if os.path.isfile(self.__current_file):
- name = read_string(self.__current_file)
- else:
- return None
+ name = self._get_field('current')
if name == '':
return None
else:
@@ -396,26 +402,26 @@ class Series:
return self.__base_file
def get_protected(self):
- return os.path.isfile(os.path.join(self.__series_dir, 'protected'))
+ return os.path.isfile(os.path.join(self.dir(), 'protected'))
def protect(self):
- protect_file = os.path.join(self.__series_dir, 'protected')
+ protect_file = os.path.join(self.dir(), 'protected')
if not os.path.isfile(protect_file):
create_empty_file(protect_file)
def unprotect(self):
- protect_file = os.path.join(self.__series_dir, 'protected')
+ protect_file = os.path.join(self.dir(), 'protected')
if os.path.isfile(protect_file):
os.remove(protect_file)
def get_description(self):
- if os.path.isfile(self.__descr_file):
- return read_string(self.__descr_file)
- else:
- return ''
+ return self._get_field('description')
+
+ def set_description(self, line):
+ self._set_field('description', line)
def __patch_is_current(self, patch):
- return patch.get_name() == read_string(self.__current_file)
+ return patch.get_name() == self.get_current()
def patch_applied(self, name):
"""Return true if the patch exists in the applied list
@@ -481,10 +487,10 @@ class Series:
create_dirs(bases_dir)
- create_empty_file(self.__applied_file)
- create_empty_file(self.__unapplied_file)
- create_empty_file(self.__descr_file)
- os.makedirs(os.path.join(self.__series_dir, 'patches'))
+ self.create_empty_field('applied')
+ self.create_empty_field('unapplied')
+ self.create_empty_field('description')
+ os.makedirs(os.path.join(self.dir(), 'patches'))
os.makedirs(self.__refs_dir)
self.__begin_stack_check()
@@ -493,15 +499,15 @@ class Series:
unconvert to place the patches in the same directory with
series control files
"""
- if self.__patch_dir == self.__series_dir:
+ if self.__patch_dir == self.dir():
print 'Converting old-style to new-style...',
sys.stdout.flush()
- self.__patch_dir = os.path.join(self.__series_dir, 'patches')
+ self.__patch_dir = os.path.join(self.dir(), 'patches')
os.makedirs(self.__patch_dir)
for p in self.get_applied() + self.get_unapplied():
- src = os.path.join(self.__series_dir, p)
+ src = os.path.join(self.dir(), p)
dest = os.path.join(self.__patch_dir, p)
os.rename(src, dest)
@@ -513,7 +519,7 @@ class Series:
for p in self.get_applied() + self.get_unapplied():
src = os.path.join(self.__patch_dir, p)
- dest = os.path.join(self.__series_dir, p)
+ dest = os.path.join(self.dir(), p)
os.rename(src, dest)
if not os.listdir(self.__patch_dir):
@@ -522,7 +528,7 @@ class Series:
else:
print 'Patch directory %s is not empty.' % self.__name
- self.__patch_dir = self.__series_dir
+ self.__patch_dir = self.dir()
def rename(self, to_name):
"""Renames a series
@@ -536,7 +542,7 @@ class Series:
git.rename_branch(self.__name, to_name)
- if os.path.isdir(self.__series_dir):
+ if os.path.isdir(self.dir()):
rename(os.path.join(self.__base_dir, 'patches'),
self.__name, to_stack.__name)
if os.path.exists(self.__base_file):
@@ -556,7 +562,7 @@ class Series:
new_series = Series(target_series)
# generate an artificial description file
- write_string(new_series.__descr_file, 'clone of "%s"' % self.__name)
+ new_series.set_description('clone of "%s"' % self.__name)
# clone self's entire series as unapplied patches
patches = self.get_applied() + self.get_unapplied()
@@ -590,6 +596,8 @@ class Series:
os.remove(fname)
os.rmdir(self.__trash_dir)
+ # FIXME: find a way to get rid of those manual removals
+ # (move functionnality to StgitObject ?)
if os.path.exists(self.__applied_file):
os.remove(self.__applied_file)
if os.path.exists(self.__unapplied_file):
@@ -602,7 +610,7 @@ class Series:
os.rmdir(self.__patch_dir)
else:
print 'Patch directory %s is not empty.' % self.__name
- if not os.listdir(self.__series_dir):
+ if not os.listdir(self.dir()):
remove_dirs(os.path.join(self.__base_dir, 'patches'),
self.__name)
^ permalink raw reply related
* Re: git and bzr
From: Jakub Narebski @ 2006-11-30 0:30 UTC (permalink / raw)
To: git; +Cc: bazaar-ng
In-Reply-To: <87bqmpvlxf.wl%cworth@cworth.org>
Carl Worth wrote:
> In the thread on the fedora
> mailing list that prompted my first "user-interface warts" and the
> patch I mentioned above, the process was worse:
>
> git commit
> "hmm... why didn't that work"
> read message
> git update-index
> git commit
> "crap... it still didn't work even when I did what it told me to do"
>
> Here's the original version of that report:
>
> https://www.redhat.com/archives/fedora-maintainers/2006-November/msg00141.html
From the SYNOPSIS of git-update-index(1) one can see that git-update-index
needs files to act on.
But I agree that git is not very user friendly, and has some usability
warts.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* Re: Some tips for doing a CVS importer
From: Michael Haggerty @ 2006-11-30 0:35 UTC (permalink / raw)
To: Markus Schiltknecht; +Cc: Jon Smirl, Git Mailing List, dev, Shawn Pearce
In-Reply-To: <456C5363.6040409@bluegap.ch>
[-- Attachment #1: Type: text/plain, Size: 8538 bytes --]
Markus Schiltknecht wrote:
> Michael Haggerty wrote:
>> This is the part that can get quite expensive for large repositories, as
>> there can be orders of magnitude more symbol creations than revisions.
>> According to Daniel Jacobowitz:
>>
>>> [...] at one point I believe the GCC repository was gaining up
>>> to four tags a day (head, two supported release branches, and one
>>> vendor branch). I've been using the principal that the number of tags
>>> might be unworkable, but the number of branches generally is not.
>>
>> This means that the number of tag events is O(number-of-days *
>> total-number-of-files-in-repo), where the gcc repo has about 50000
>> files. By contrast, only a small fraction of files is typically touched
>> in any day.
>
> Yeah, 50'000 * 1825 (5 years) * say 100 bytes -> 8GB sounds like a lot.
> OTOH, I certainly don't need 100 bytes per tag and one tag per day over
> five years is really a lot. Repositories that large are probably not
> converted to CVS on an old Pentium III...
...times 4 (tags per day) -> 32GB. If I understand correctly, the tags
were created nightly by automated scripts.
I admit that this is an extreme example, but the philosophy of the
cvs2svn project (a philosophy that I inherited from my predecessors, by
the way) is to be able to handle the most absurd repositories out there.
> Well, almost. I meant a whole repository with these branches. If one
> file included all the branches it's getting easy to resolve. But for my
> example, I had something like that in mind:
I am glad that we are getting into concrete examples. But your example
needs some clarifications (see below).
> fileA:
>
> A = 1.2.2
> (no changes for branch B)
> C = 1.2.4 --> makes A a possible parent of branch C
In this case, ROOT can also be C's parent.
> D = 1.2.2.5.2 --> makes A a possible parent of branch D
This implies that A is *necessarily* the parent of D. If there were a
E=1.2.2.5.4, then the parent of E would be ambiguous but the parent of D
would still unambiguously be A.
> X = 1.2.4 --> makes C a possible parent of tag X
Wait a minute. A tag always has an even number of integers. Do you
mean X=1.2 or X=1.2.4.1? The same below.
> fileB:
>
> A = 1.2.2
> B = 1.2.4 --> makes A a possible parent of branch B
or ROOT
> C = 1.2.6 --> makes B a possible parent of branch C
or A or ROOT
> D = 1.2.2.5.2 --> makes A a possible parent of branch D
A is unambiguously the parent of D
> X = 1.2.2.5.2 --> makes D a possible parent of tag X
>
> fileC:
> A = 1.2.2
> X = 1.2.2 --> makes A a possible parent of tag X
>
> fileD:
> A = 1.2.2
> B = 1.2.4
> X = 1.2.4 --> makes B a possible parent of tag X
>
>>> The symbol blob for branch A: has only one possible parent: ROOT. Thus I
>>> assign A->parent_branch = ROOT.
>>>
>>> Next comes the blob for branch C: it has two possible parents: branch B
>>> and branch A.
>>
>> Why is ROOT not considered as a possible parent of C?
>
> Those were just examples. In my CVS-repository-in-mind, none of the
> files were branching from ROOT directly into C.
In your example, ROOT *is* a possible parent of C.
>>> At that point we know that A is derived from ROOT, but we
>>> don't have assigned a parent to B, yet. Thus we can not resolve C this
>>> time.
>>>
>>> Then comes branch B: one parent: A. Mark it.
In your example, ROOT is also a possible parent of B.
>>> Next round, we process C again: this time, we know B is branched from A.
>>> Thus we can remove the possible parent A. Leaving only one possible
>>> parent branch: B.
>>
>> But the fact that B preceded C chronologically does not mean that C is
>> derived from B.
>
> No. And I don't assume so in any place. Given the files above, I can
> however clearly say that C got branched off from B, no?
No. C is nowhere unambiguously derived from B, therefore its parent
could be ROOT, A, or B. See my example below.
>> If I branch from ROOT or A after creating branch B, the
>> result as stored in CVS looks exactly the same as if I branch from B
>> (unless a file was modified between the creation of the parent branch
>> and the creation of the child branch).
>
> Sure. That would result in an unresolvable symbol.
>
>>> Now, say we have a tag 'X', which ended up in a blob having A, B, C and
>>> D as possible parent branches. I currently remove A and B, as they are
>>> parents of C. But C and D still remain and conflict. I'm unable to
>>> resolve that symbol. I'm thinking about leaving such conflicts to the
>>> user to resolve.
I don't know how to deal with tag X because the numbers that you
assigned to it above can't be correct.
Consider the attached script. It unambiguously creates branches A1 and
A2 from ROOT and branch B from A1, then adds tag X on branch B. But in
the files:
fileA symbols
X:1.1
B:1.1.0.6
A2:1.1.0.4
A1:1.1.0.2;
fileB symbols
X:1.1.2.1
B:1.1.2.1.0.2
A2:1.1.0.4
A1:1.1.0.2;
fileC symbols
X:1.1.6.1
B:1.1.0.6
A2:1.1.0.4
A1:1.1.0.2;
fileD symbols
X:1.1
B:1.1.0.4
A2:1.2.0.2
A1:1.1.0.2;
Note that from looking at fileA alone, there is no way to tell whether
A2 was created from ROOT or A1, or whether B was created from ROOT, A1,
or A2. And tag X is all over the place, even though for each file it
was created from branch B.
If only information from fileA,v is considered, any of the following
branching topologies would give identical fileA,v contents:
ROOT
/|\
/ | \
A1 A2 B
ROOT
/ \
/ \
A1 A2
|
B
ROOT
/ \
/ \
A1 A2
|
B
ROOT
/ \
/ \
A1 B
|
A2
ROOT
|
A1
/ \
/ \
A2 B
ROOT
|
A1
|
A2
|
B
And from the information present in fileA,v, it is not possible to tell
whether tag X was applied to ROOT, A1, A2, or B.
(Some topologies *are* ruled out because the revision numbers are
ordered incorrectly; for example:
ROOT
|
B
/ \
/ \
A1 A2
ROOT
|
A2
|
A1
|
B
are not consistent with fileA,v.)
If we also consider the information in fileB, it is clear that branch
B's parent is branch A1, but it is still not clear whether branch A2's
parent is ROOT or A1, or whether tag X was applied to branch A1, A2, or B.
Similarly, fileC,v tells us that tag X was applied to branch B, and
fileD,v tells us that A2's parent is ROOT.
Each file alone is quite ambiguous, but in this case putting the
information from all files together (with the assumption that they have
a mutually-consistent history) is enough to reconstruct the entire
branching topology.
What's worse in real life? Each file rules out some possible histories
and the goal is to find a history that is consistent with all files. But...
- There can easily be cases where even the total information from all
files is still not enough to choose a unique history. In such cases we
need a way to select between the possible histories.
- Since files in CVS don't necessarily *have* a globally consistent
branching/tagging history, heuristics have to be used in such cases to
find histories that apply to subsets of the repository in some
reasonable way (i.e., the one that is most likely considering the way
people typically work with CVS).
- "Unlabeled branches": often users have removed the label from a
branch, but the branch is still used as a source for other branches.
Figuring out this situation is a real mess.
I imagine that the best results (never mind whether it is practical)
would be obtained by recording the topology constraints implied by each
*,v file, then trying to map the topologies onto each other pair by pair
to (1) combine the constraints and thereby limit the possible histories
and (2) deduce which unlabeled branches correspond to one another. But
I still don't know how to deal with inconsistent histories. I think a
bottom-up approach would be the most sensible, given that people are
probably more likely to tag a whole subdirectory rather than files
scattered here and there.
The second step is to decide at what point in time a branch or tag
should be created, with the goal of being able to create it as a
snapshot of the source branch at that moment. This is not always
possible, even if the branch topologies are compatible.
Michael
[-- Attachment #2: makerepo.sh --]
[-- Type: application/x-shellscript, Size: 626 bytes --]
^ permalink raw reply
* Re: Some tips for doing a CVS importer
From: Daniel Jacobowitz @ 2006-11-30 0:45 UTC (permalink / raw)
To: Michael Haggerty
Cc: Markus Schiltknecht, Jon Smirl, Git Mailing List, dev,
Shawn Pearce
In-Reply-To: <456E2746.4050707@alum.mit.edu>
On Thu, Nov 30, 2006 at 01:35:18AM +0100, Michael Haggerty wrote:
> ...times 4 (tags per day) -> 32GB. If I understand correctly, the tags
> were created nightly by automated scripts.
Correct. Remember, checking out a branch from a CVS repository from a
particular date was extremely awkward; the tags were the only way to
have reproducible snapshots.
--
Daniel Jacobowitz
^ permalink raw reply
* Re: [PATCH 0/2] Making "git commit" to mean "git commit -a".
From: Daniel Barkalow @ 2006-11-30 0:52 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Carl Worth, git
In-Reply-To: <7virgzuf38.fsf@assigned-by-dhcp.cox.net>
On Tue, 28 Nov 2006, Junio C Hamano wrote:
> The above paragraph is not the important part of my message.
> What was much more important is what immediately followed it,
> which you did not quote:
>
> And at that point, I trust "git commit" to do the right thing --
> the damn thing I just checked with "git diff --cached" _is_ what
> will be committed.
Perhaps you'd be happier if the command to commit what "git diff --cached"
shows were "git commit --cached" rather than "git commit -i"? (Or if they
were both --index; how did we miss that last September?)
It seems logical to me that "git commit" would commit the changes shown by
"git diff" (in addition to changes in the index, of course, which are so
obvious as to need no mention). I personally check with "git diff" and
commit if everything there looks good; otherwise I tweak stuff until it
does. And if there are a lot of changes, and all of those in some files
look good, but those in other files need work, I can "git update-index"
the ones I know I like so I don't have to go through them each time I'm
checking on other stuff next time.
> This is where "git commit" that does "-a" by default goes quite
> against the underlying mental model of git. You staged what
> should appear in the next commit in the index because you did
> not want to worry about the local changes you still want to keep
> in your working tree.
That is not so clear to me. Maybe you're putting changes into the index to
reduce the noise in "git diff", by updating everything that's
unquestionable while you examine the other stuff. I think that everything
in the index is clearly in the next commit, but it's obviously not true
that everything in the next commit is in the index (because you might not
be done updating things yet).
> Doing the "screw the index" commit by default to these people is slap in
> the face. You do not want to get your index suddenly screwed at the
> final moment of making the commit, which happened to me when I did
> "commit --amend" with the version with those two patches applied.
I personally think that --amend should default to retaining the same tree,
with options available for using the index or -a or paths. Using the index
by default is just as wrong as -a; you're just more careful about it by
experience. The index holds stuff to go in the *next* commit, but --amend
generates a new version of the *previous* commit, so the logical basis for
the new previous commit is the old previous commit's tree, leaving the
index alone.
-Daniel
^ permalink raw reply
* Re: [PATCH 0/2] Making "git commit" to mean "git commit -a".
From: Junio C Hamano @ 2006-11-30 1:03 UTC (permalink / raw)
To: Carl Worth; +Cc: Nicolas Pitre, git
In-Reply-To: <87ejrlvn7r.wl%cworth@cworth.org>
Carl Worth <cworth@cworth.org> writes:
> I think what I'm asking for is a much more mild change. The "keep the
> index clean" behavior exists almost everywhere already, (the few
> exceptions are things like "git cherry-pick -n", and the notable
> exception of a conflicted merge). So I don't think supporting "commit
> -a by default" means we have to introduce a large conceptual change.
We seem to be agreeing (and Linus seems to, too, in a thread
next door) that it is a good thing that git keeps index clean
unless you explicitly ask it to.
We also seem to be agreeing that people with more involved needs
can deliberately make index different from HEAD, way before
issuing "git commit", and that they can commit even when "git
diff" gives nonempty differences, and these are good things.
Are we on the same page?
Now what does it mean to make "commit" silently update the index
with all the changes in the working tree without being told?
Unless you are introducing "working tree is the king" mode to
git to make everything ignore the index's "contents" part (in
other words, the index is used as the CVS/Entries file, nothing
more, under that mode of operation), I think you just introduced
an inconsistency at the place where the difference matters most.
I do not agree what you are asking is a "mild change" at all,
and I said it already that it goes against the mental model of
how git tools work.
Earlier, the world model was "you build it in the index and you
make a commit of what is in the index; there is a last-minute
index operation you can do by passing paths to commit and as a
short-hand there is -a as well [*1*]". Now you made the world
model "it does not matter what you have in the index before
issuing git-commit; if you want to preserve what you built in
the index, you have to do something non-default". That WOULD
solicit more newbie confusion. "If it does not matter at the
end unless you do something special, why bother doing it at
all?" would be the question you would face.
Earlier on the "UI warts" thread, people said that the users do
not form the mental model of how the toolset works by reading
the tool's documentation but by trying things out, and I think
that is a valid observation. We should not be sending a wrong
message by introducing inconsistencies like that.
The tool's UI should naturally reflect what world model it is
based on, and like it or not, the world model of git includes
the index. The way to explain "-a" to new users should not be
"you can _ignore_ index as long as you use -a". I do not think
denying the index buys the new users anything. Rather,
"building your next commit incrementally in the index is the
workflow git is designed to support, but you are not required to
do that _incrementally_. Until you encounter a complex
situation such as resolving a large conflicting merge, doing
that incrementally does not buy you anything as long as you work
in a clean working tree. Instead, you can tell git what you
want to commit when you run 'git-commit' by giving paths or
directory names, or if you want to commit everything in the
working tree, then you can also say '-a'".
I am all for rewording the cryptic "use update-index to update"
message with "use 'commit -a' to commit all of them" or
somesuch. That does NOT break the mental model.
Another thing that we need to be aware of is that new users
won't be "newbies" forever, and the tool should not be optimized
for the first few pages of the tutorial. You and Nico say
"experienced people can always alias UI warts away", but I think
that is a wrong attitude. Users with experience, long after
this discussion is forgotten, would complain "other tools help
us build the next commit in the index, but git-commit by default
discards the distinction between what were marked for commit and
what were not, unless explicitly told not to. Why does it do -a
by default, and why should I forced to alias that stupid default
away?"
[Footnote]
*1* In retrospect, making "commit -o" the default was a very bad
change; I got tired of repeating myself in that discussion and
applied that change, but it was probably a mistake.
^ permalink raw reply
* Re: [PATCH 0/2] Making "git commit" to mean "git commit -a".
From: Junio C Hamano @ 2006-11-30 1:22 UTC (permalink / raw)
To: Carl Worth; +Cc: Nicolas Pitre, git
In-Reply-To: <7vodqpn3t4.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> writes:
> ... Rather,
> "building your next commit incrementally in the index is the
> workflow git is designed to support, but you are not required to
> do that _incrementally_. Until you encounter a complex
> situation such as resolving a large conflicting merge, doing
> that incrementally does not buy you anything as long as you work
> in a clean working tree.
Side note. I think the above "Until..." is an overstatement,
and maybe the readers of the tutorial can be taught a lot
earlier how the index can help them. Maybe the following
sequence can be added to an early part of the tutorial sequence?
$ edit hello.c
$ make test
$ git diff
$ git update-index hello.c; # ok, that is good so far.
$ edit hello.c; # hack more
$ make test; # oops, does not work
$ git diff; # ah, that overeager edit broken what was good
$ git checkout hello.c; # get the last good one back
^ permalink raw reply
* Re: [PATCH 0/2] Making "git commit" to mean "git commit -a".
From: Steven Grimm @ 2006-11-30 1:58 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vk61dn2yj.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano wrote:
> Side note. I think the above "Until..." is an overstatement,
> and maybe the readers of the tutorial can be taught a lot
> earlier how the index can help them. Maybe the following
> sequence can be added to an early part of the tutorial sequence?
>
> $ edit hello.c
> $ make test
> $ git diff
> $ git update-index hello.c; # ok, that is good so far.
> $ edit hello.c; # hack more
> $ make test; # oops, does not work
> $ git diff; # ah, that overeager edit broken what was good
> $ git checkout hello.c; # get the last good one back
>
That actually points out one of the things I think isn't so hot about
using update-index for checkpointing your work. Here's a longer
development session:
$ edit hello.c
$ make test
$ git update-index hello.c; # so far so good
$ edit hello.c
$ make test
$ git update-index hello.c; # looks good too
$ edit hello.c
$ make test
$ git update-index hello.c; # sure, seems okay
$ edit hello.c
$ make test; # oops! design flaw in the second edit uncovered!
$ ???; # how do I back out the last three edits but not the first?
If you know for certain that you will only ever want to back out the
most recent edit during your development, or back out all the way to
HEAD, then update-index is fine, but if (like me) you want to checkpoint
your work frequently so you can step back in a very fine-grained
fashion, then it's less than ideal to have only one checkpoint that
keeps getting overwritten.
For frequent checkpointing, as far as I can tell I pretty much need to
commit (to a development branch, of course) every time. I do that
because I never know beforehand whether I'll need to go back by more
than one step later on; 99% of the time I don't have to, of course, but
the remaining 1% is pretty painful if I can't.
Am I missing some magic index command that would support multi-level
backing out? Obviously StGIT is an option as well, but that seems like
overkill when all I want is to checkpoint my work. The above is why,
even though (I think) I know enough about the index to use it as you
describe, I often don't bother and just run "commit -a" during
development instead. When I merge, I usually fold all my checkpoint
commits together and merge the change as a logical unit.
But I'm still a relative n00b and would appreciate knowing if I'm just
missing some big obvious technique.
^ permalink raw reply
* Re: [PATCH 0/2] Making "git commit" to mean "git commit -a".
From: Sam Vilain @ 2006-11-30 2:04 UTC (permalink / raw)
To: Steven Grimm; +Cc: Junio C Hamano, git
In-Reply-To: <456E3AB7.1030306@midwinter.com>
Steven Grimm wrote:
> Am I missing some magic index command that would support multi-level
> backing out? Obviously StGIT is an option as well, but that seems like
> overkill when all I want is to checkpoint my work. The above is why,
> even though (I think) I know enough about the index to use it as you
> describe, I often don't bother and just run "commit -a" during
> development instead. When I merge, I usually fold all my checkpoint
> commits together and merge the change as a logical unit.
>
Try `git commit --amend'.
^ permalink raw reply
* Re: [PATCH 0/2] Making "git commit" to mean "git commit -a".
From: Johannes Schindelin @ 2006-11-30 2:11 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Carl Worth, Nicolas Pitre, git
In-Reply-To: <7vk61dn2yj.fsf@assigned-by-dhcp.cox.net>
Hi,
On Wed, 29 Nov 2006, Junio C Hamano wrote:
> Junio C Hamano <junkio@cox.net> writes:
>
> > ... Rather,
> > "building your next commit incrementally in the index is the
> > workflow git is designed to support, but you are not required to
> > do that _incrementally_. Until you encounter a complex
> > situation such as resolving a large conflicting merge, doing
> > that incrementally does not buy you anything as long as you work
> > in a clean working tree.
>
> Side note. I think the above "Until..." is an overstatement,
> and maybe the readers of the tutorial can be taught a lot
> earlier how the index can help them. Maybe the following
> sequence can be added to an early part of the tutorial sequence?
>
> $ edit hello.c
> $ make test
> $ git diff
> $ git update-index hello.c; # ok, that is good so far.
> $ edit hello.c; # hack more
> $ make test; # oops, does not work
> $ git diff; # ah, that overeager edit broken what was good
> $ git checkout hello.c; # get the last good one back
I like it. Sort of a "temporary commit" to check against.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH 0/2] Making "git commit" to mean "git commit -a".
From: Junio C Hamano @ 2006-11-30 2:12 UTC (permalink / raw)
To: Steven Grimm; +Cc: git
In-Reply-To: <456E3AB7.1030306@midwinter.com>
Steven Grimm <koreth@midwinter.com> writes:
> But I'm still a relative n00b and would appreciate knowing if I'm just
> missing some big obvious technique.
You are doing just fine. Using commits to do snapshot is
another workflow people often use. These people tend to do so
in a work branch and cherry-pick the resulting series of commits
onto more permanent branch while reorganizing and tidying up the
development history to be published to the outside world.
^ permalink raw reply
* [PATCH] git-branch: let caller specify logmsg
From: Lars Hjemli @ 2006-11-30 2:16 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
This changes the signature of rename_ref() in refs.[hc] to include a
logmessage for the reflogs.
Also, builtin-branch.c is modified to provide a proper logmessage + call
setup_ident() before any logmessages are written.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
builtin-branch.c | 8 ++++++--
refs.c | 10 +++-------
refs.h | 2 +-
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/builtin-branch.c b/builtin-branch.c
index 3e206b9..abf23c4 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -247,7 +247,7 @@ static void create_branch(const char *name, const char *start,
static void rename_branch(const char *oldname, const char *newname, int force)
{
- char oldref[PATH_MAX], newref[PATH_MAX];
+ char oldref[PATH_MAX], newref[PATH_MAX], logmsg[PATH_MAX*2 + 100];
unsigned char sha1[20];
if (snprintf(oldref, sizeof(oldref), "refs/heads/%s", oldname) > sizeof(oldref))
@@ -265,7 +265,10 @@ static void rename_branch(const char *oldname, const char *newname, int force)
if (resolve_ref(newref, sha1, 1, NULL) && !force)
die("A branch named '%s' already exists.", newname);
- if (rename_ref(oldref, newref))
+ snprintf(logmsg, sizeof(logmsg), "Branch: renamed %s to %s",
+ oldref, newref);
+
+ if (rename_ref(oldref, newref, logmsg))
die("Branch rename failed");
if (!strcmp(oldname, head) && create_symref("HEAD", newref))
@@ -281,6 +284,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
int kinds = REF_LOCAL_BRANCH;
int i;
+ setup_ident();
git_config(git_default_config);
for (i = 1; i < argc; i++) {
diff --git a/refs.c b/refs.c
index d8c19e6..d45f267 100644
--- a/refs.c
+++ b/refs.c
@@ -784,13 +784,12 @@ int delete_ref(const char *refname, unsigned char *sha1)
return ret;
}
-int rename_ref(const char *oldref, const char *newref)
+int rename_ref(const char *oldref, const char *newref, const char *logmsg)
{
static const char renamed_ref[] = "RENAMED-REF";
unsigned char sha1[20], orig_sha1[20];
int flag = 0, logmoved = 0;
struct ref_lock *lock;
- char msg[PATH_MAX*2 + 100];
struct stat loginfo;
int log = !lstat(git_path("logs/%s", oldref), &loginfo);
@@ -806,14 +805,11 @@ int rename_ref(const char *oldref, const char *newref)
if (!is_refname_available(newref, oldref, get_loose_refs(), 0))
return 1;
- if (snprintf(msg, sizeof(msg), "renamed %s to %s", oldref, newref) > sizeof(msg))
- return error("Refnames to long");
-
lock = lock_ref_sha1_basic(renamed_ref, NULL, NULL);
if (!lock)
return error("unable to lock %s", renamed_ref);
lock->force_write = 1;
- if (write_ref_sha1(lock, orig_sha1, msg))
+ if (write_ref_sha1(lock, orig_sha1, logmsg))
return error("unable to save current sha1 in %s", renamed_ref);
if (log && rename(git_path("logs/%s", oldref), git_path("tmp-renamed-log")))
@@ -866,7 +862,7 @@ int rename_ref(const char *oldref, const char *newref)
lock->force_write = 1;
hashcpy(lock->old_sha1, orig_sha1);
- if (write_ref_sha1(lock, orig_sha1, msg)) {
+ if (write_ref_sha1(lock, orig_sha1, logmsg)) {
error("unable to write current sha1 into %s", newref);
goto rollback;
}
diff --git a/refs.h b/refs.h
index ce73d5c..51aab1e 100644
--- a/refs.h
+++ b/refs.h
@@ -48,6 +48,6 @@ extern int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned
extern int check_ref_format(const char *target);
/** rename ref, return 0 on success **/
-extern int rename_ref(const char *oldref, const char *newref);
+extern int rename_ref(const char *oldref, const char *newref, const char *logmsg);
#endif /* REFS_H */
--
1.4.4.1.gf0df
^ permalink raw reply related
* [PATCH] git-merge: preserve and merge local changes when doing fast forward
From: Junio C Hamano @ 2006-11-30 3:02 UTC (permalink / raw)
To: git
The idea and the logic are identical to what "checkout -m" does
when switching the branches. Instead of refusing the two-way
merge, perform the three-way merge between the old head, the
working tree and the new head, and leave the (potentially
conflicted) merge result in the working tree.
If this turns out to be a sane thing to do, we probably should
make the common logic between "checkout -m" and this into a
built-in command.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
* I am not sure if this is worth doing in general; it can leave
a huge mess if the conflict with the merge and the local
change is too extensive and does not give a good way to
recover from it, and that is why we require an explicit "-m"
to "git checkout" for this behaviour. Perhaps we would want
a new option to git-merge to allow preserving the local
changes, but the obvious candidate -m is taken for something
else per recent popular request X-<...
git-merge.sh | 42 +++++++++++++++++++++++++++++++++++++++++-
1 files changed, 41 insertions(+), 1 deletions(-)
diff --git a/git-merge.sh b/git-merge.sh
index 75af10d..324991f 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -91,6 +91,46 @@ finish () {
esac
}
+merge_local_changes () {
+ merge_error=$(git-read-tree -m -u $1 $2 2>&1) || (
+ # Match the index to the working tree, and do a three-way.
+ git diff-files --name-only |
+ git update-index --remove --stdin &&
+ work=`git write-tree` &&
+ git read-tree --reset -u $2 &&
+ git read-tree -m -u --aggressive $1 $2 $work || exit
+
+ echo >&2 "Carrying local changes forward."
+ if result=`git write-tree 2>/dev/null`
+ then
+ echo >&2 "Trivially automerged."
+ else
+ git merge-index -o git-merge-one-file -a
+ fi
+
+ # Do not register the cleanly merged paths in the index
+ # yet; this is not a real merge before committing, but
+ # just carrying the working tree changes along.
+ unmerged=`git ls-files -u`
+ git read-tree --reset $2
+ case "$unmerged" in
+ '') ;;
+ *)
+ (
+ z40=0000000000000000000000000000000000000000
+ echo "$unmerged" |
+ sed -e 's/^[0-7]* [0-9a-f]* /'"0 $z40 /"
+ echo "$unmerged"
+ ) | git update-index --index-info
+
+ echo >&2 "Conflicts in locally modified files:"
+ git diff --name-only --diff-filter=U >&2
+ ;;
+ esac
+ exit 0
+ )
+}
+
case "$#" in 0) usage ;; esac
rloga= have_message=
@@ -264,7 +304,7 @@ f,*)
echo "Updating $(git-rev-parse --short $head)..$(git-rev-parse --short $1)"
git-update-index --refresh 2>/dev/null
new_head=$(git-rev-parse --verify "$1^0") &&
- git-read-tree -u -v -m $head "$new_head" &&
+ merge_local_changes $head $new_head &&
finish "$new_head" "Fast forward"
dropsave
exit 0
--
1.4.4.1.gc419
^ permalink raw reply related
* Re: [PATCH 0/2] Making "git commit" to mean "git commit -a".
From: Linus Torvalds @ 2006-11-30 3:10 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Junio C Hamano, Carl Worth, Nicolas Pitre, git
In-Reply-To: <Pine.LNX.4.63.0611300310520.30004@wbgn013.biozentrum.uni-wuerzburg.de>
On Thu, 30 Nov 2006, Johannes Schindelin wrote:
>
> I like it. Sort of a "temporary commit" to check against.
I (very) occasionally do this for patches I get.
You can do
git-apply --index patch
and it will apply the patch and update the index for you. That's great for
committing the patch (because it means that it adds and removes your files
automatically for you), but most of the time when I get an email that I
want to apply, I just use "git-applymbox".
So where doing the "git apply --index" thing is great is when you see a
patch that has some obvious deficiency that makes you not want to commit
it directly, but add some fixup of your own.
That's when it's useful to use the index to your advantage - you can do
"git diff" (to see just the fixups you did on top of the patch), or you
can do "git diff HEAD" (to see the combined effect of both the patch _and_
your fixups).
That said, I have to admit that I usually (a) don't do this very often (ie
this is not part of my daily routine) and (b) I tend to do "git reset"
fairly soon afterwards (or alternatively, just "git commit -a") to get
back to the situation where the index will match the current HEAD 100%
again. So the "index doesn't match HEAD" situation is always just a
_temporary_ thing for me.
^ permalink raw reply
* v2.6.11 tag in kernel tree
From: Jon Smirl @ 2006-11-30 4:02 UTC (permalink / raw)
To: Git Mailing List
Using this tree git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
These two tags appear to be pointing to a tree instead of a commit.
v2.6.11
v2.6.11-tree
I'm trying to check out v2.6.11 so that I can figure out the changes a
vendor made to it.
jonsmirl@jonsmirl:/extra/linux$ git checkout -b microcross v2.6.11
Cannot switch branch to a non-commit.
I can checkout the other tags without problem.
What's the secret to checking out 2.6.11?
--
Jon Smirl
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox