* Re: Creating something like increasing revision numbers
From: alexandrul @ 2009-10-18 15:29 UTC (permalink / raw)
To: Norbert Preining; +Cc: git
In-Reply-To: <20091018144158.GA9789@gandalf.dynalias.org>
Norbert Preining wrote:
> My idea is that git - like subversion - could (if asked to) count each
> commit (global to the repository, irrelevant of the branch) and give it
> a version number. Since we all will use a bare repository on a server
> and pull/push from/to there, I think that something similar could be possible.
I was thinking to set a post-commit hook that reads the current version
from a file, increment and save it, and also set a tag with that value.
Being a DVCS, this kind of versioning can only be trusted on a single repo,
but if you set it on the "main" repo, it should work.
The only drawback could be the ever growing number of tags,
I don't know how it will work with thousands of tags or more.
Have a nice day,
A.
^ permalink raw reply
* Re: Creating something like increasing revision numbers
From: Norbert Preining @ 2009-10-18 15:20 UTC (permalink / raw)
To: Johan Herland; +Cc: git
In-Reply-To: <200910181703.20607.johan@herland.net>
On So, 18 Okt 2009, Johan Herland wrote:
> A global, increasing version number ala SVN is fundamentally impossible in
> any distributed version control system (like Git).
Yes, agreed.
The point is that I do not actually need the "distributed" part of git.
I want one central repository and all collaborators commit to that.
Yes, that is subversion, I know.
We have no branches, no tags, nothing of that. Only trunk.
> $ git describe
> v1.0.4-14-g2414721
>
> where the "v1.0.4" part is the last tag that the current state is based on,
> the "14" part is the number of commit between that tag and the current
So if we have only one tag (initial) then it would count the number
of commits?
And if yes, is it easy to find out at which commit a file has been changed
last time (svn status -v).
I have read a lot on the net about the impossibility, and I agree that
in a distributed setting it does not work.
And in fact we would not even have revision numbers on our local
git repositories. Only one (the master checkout from which our
distribution server is updated) needs to have some commit numbers.
THe reason is that we use that as serial number for packages. One packages
is roughly on package from CTAN (Comprehensive TeX Archive Network,
like CPAN), and we want to make sure that if that is updated on CTAN
and we import it into our system, the next time we create a TeX Live
package for it (that will be served to quite a lot of users) we have
a new version number.
We first thought about using the version number as provided by authors,
but that is completely useless, because there are tooo many authors
of packages on CTAN where the version numbers are in no way increasing ;-)
So we settled for the max of all the last changed revision number of
the contained files, whcih is guaranteed to increase.
As a lat resort I will try to use git-svn ...
Again, thanks a lot and all the best
Norbert
-------------------------------------------------------------------------------
Dr. Norbert Preining Associate Professor
JAIST Japan Advanced Institute of Science and Technology preining@jaist.ac.jp
Vienna University of Technology preining@logic.at
Debian Developer (Debian TeX Task Force) preining@debian.org
gpg DSA: 0x09C5B094 fp: 14DF 2E6C 0307 BE6D AD76 A9C0 D2BF 4AA3 09C5 B094
-------------------------------------------------------------------------------
QUOYNESS (n.)
The hatefulness of words like 'relionus' and 'easiephit'.
--- Douglas Adams, The Meaning of Liff
^ permalink raw reply
* Re: Creating something like increasing revision numbers
From: Johan Herland @ 2009-10-18 15:03 UTC (permalink / raw)
To: Norbert Preining; +Cc: git
In-Reply-To: <20091018144158.GA9789@gandalf.dynalias.org>
On Sunday 18 October 2009, Norbert Preining wrote:
> Now, there is one show-stopper I see. From our repository we create a
> set of "packages", and the maximum of the "last-changed" revisions of
> the contained files determine the "version" of the package. This
> guarantees that any change in a file will increase the revision number
> of the package (some tricks for removals have to be done). This is
> necessary since we are distributing the packages from servers and the
> version number pf a package determines whether it should be upgraded
> (well known concept).
>
> Now my question, is there any way to set up something similar with git?
>
> My idea is that git - like subversion - could (if asked to) count each
> commit (global to the repository, irrelevant of the branch) and give it
> a version number. Since we all will use a bare repository on a server
> and pull/push from/to there, I think that something similar could be
> possible.
>
> So, before I delve into more gitty-nitty conversion, let me know if
> there is any chance for that, or we should stay with subversion.
A global, increasing version number ala SVN is fundamentally impossible in
any distributed version control system (like Git).
However, you can get a useful version specifier from the "git describe"
command. It will give you back something like the following:
$ git describe
v1.0.4-14-g2414721
where the "v1.0.4" part is the last tag that the current state is based on,
the "14" part is the number of commit between that tag and the current
state, and the "2414721" is the abbreviated object name (SHA1 id) for the
current commit itself.
This is somewhat more complex than a simple version number, but guarantees a
globally unique name for your current state that works in a distributed
environment.
Also, I find "v1.0.4-14..." (i.e. 14 commits since v1.0.4) much more useful
than, say, "12534" (i.e. 12534 commits since the start of the project).
See 'git help describe for more info'
Have fun! :)
...Johan
--
Johan Herland, <johan@herland.net>
www.herland.net
^ permalink raw reply
* Creating something like increasing revision numbers
From: Norbert Preining @ 2009-10-18 14:41 UTC (permalink / raw)
To: git
Dear all,
(please Cc)
I am managing some of my projects with git and I am quite happy about it.
There is another project I am working that is quite big, the subversion
checkout is about 14Gb. Doing svn up is a pain, it has to open tens of
thousands of files and directories traversing the whole tree, trashing
the fs cache and taking ages.
My idea was to move to git, from what I read it should be more capable
in handling these type of projects.
Now, there is one show-stopper I see. From our repository we create a
set of "packages", and the maximum of the "last-changed" revisions of
the contained files determine the "version" of the package. This
guarantees that any change in a file will increase the revision number
of the package (some tricks for removals have to be done). This is necessary
since we are distributing the packages from servers and the version number
pf a package determines whether it should be upgraded (well known concept).
Now my question, is there any way to set up something similar with git?
My idea is that git - like subversion - could (if asked to) count each
commit (global to the repository, irrelevant of the branch) and give it
a version number. Since we all will use a bare repository on a server
and pull/push from/to there, I think that something similar could be possible.
So, before I delve into more gitty-nitty conversion, let me know if
there is any chance for that, or we should stay with subversion.
Thanks a lot and all the best
Norbert
PS: for those interested, it is TeX Live: www.tug.org/texlive
-------------------------------------------------------------------------------
Dr. Norbert Preining Associate Professor
JAIST Japan Advanced Institute of Science and Technology preining@jaist.ac.jp
Vienna University of Technology preining@logic.at
Debian Developer (Debian TeX Task Force) preining@debian.org
gpg DSA: 0x09C5B094 fp: 14DF 2E6C 0307 BE6D AD76 A9C0 D2BF 4AA3 09C5 B094
-------------------------------------------------------------------------------
YONKERS (n.)
(Rare.) The combined thrill of pain and shame when being caught in
public plucking your nostril-hairs and stuffing them into your
side-pocket.
--- Douglas Adams, The Meaning of Liff
^ permalink raw reply
* Re: [PATCH 3/3] git checkout --nodwim
From: Alex Riesen @ 2009-10-18 12:40 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Johannes Schindelin, Jay Soffian
In-Reply-To: <7v63adxh9a.fsf_-_@alter.siamese.dyndns.org>
On Sun, Oct 18, 2009 at 10:01, Junio C Hamano <gitster@pobox.com> wrote:
> + OPT_SET_INT(0, "nodwim", &dwim_new_local_branch,
> + "do not dwim local branch creation", 0),
Isn't there a special negation support for --no-something in parse-options?
^ permalink raw reply
* Re: [PATCH 2/3] DWIM "git checkout frotz" to "git checkout -b frotz origin/frotz"
From: Björn Steinbrink @ 2009-10-18 12:00 UTC (permalink / raw)
To: Nanako Shiraishi; +Cc: Junio C Hamano, git, Johannes Schindelin, Jay Soffian
In-Reply-To: <20091018193448.6117@nanako3.lavabit.com>
On 2009.10.18 19:34:48 +0900, Nanako Shiraishi wrote:
> Quoting Junio C Hamano <gitster@pobox.com>
>
> > When 'frotz' is not a valid object name nor a tracked filename,
> > we used to complain and failed this command. When there is only
> > one remote that has 'frotz' as one of its tracking branches, we can
> > DWIM it as a request to create a local branch 'frotz' forking from
> > the matching remote tracking branch.
>
> In the subject you used 'git checkout -b frotz origin/frotz'. Did you
> forget to say '-t'?
Hm, the DWIMmery only triggers when opts.track is
BRANCH_TRACK_UNSPECIFIED, i.e. -t was not used. And it doesn't change
opts.track when it DWIMs, so it respects branch.autosetupmerge, which
would be overriden by -t. So it seems correct that -t is not in there.
Björn
^ permalink raw reply
* Re: [PATCH 2/3] DWIM "git checkout frotz" to "git checkout -b frotz origin/frotz"
From: Nanako Shiraishi @ 2009-10-18 10:34 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Johannes Schindelin, Jay Soffian
In-Reply-To: <7vaazpxha4.fsf_-_@alter.siamese.dyndns.org>
Quoting Junio C Hamano <gitster@pobox.com>
> When 'frotz' is not a valid object name nor a tracked filename,
> we used to complain and failed this command. When there is only
> one remote that has 'frotz' as one of its tracking branches, we can
> DWIM it as a request to create a local branch 'frotz' forking from
> the matching remote tracking branch.
In the subject you used 'git checkout -b frotz origin/frotz'. Did you forget to say '-t'?
--
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/
^ permalink raw reply
* Re: [PATCH v3.1 3/5] Introduce new pretty formats %g[sdD] for reflog information
From: Nanako Shiraishi @ 2009-10-18 10:34 UTC (permalink / raw)
To: Jeff King; +Cc: Thomas Rast, Junio C Hamano, Jef Driesen, Nanako Shiraishi, git
In-Reply-To: <20091018071829.GA7748@coredump.intra.peff.net>
Quoting Jeff King <peff@peff.net>
> On Sat, Oct 17, 2009 at 04:48:11PM +0200, Thomas Rast wrote:
>
>> > +NOTE: Some placeholders may depend on other options given to the
>> > +revision traversal engine. For example, the `%g*` reflog options will
>> > +insert an empty string unless we are traversing reflog entries (e.g., by
>> > +`git log -g`). The `%d` placeholder will use the "short" decoration
>> > +format if `--decorate` was not already provided on the command line.
>>
>> Sure. I figured it was obvious enough, but since you already went to
>> the lengths of documenting the exact behaviour of %d, I squashed it
>> and adjusted the acknowledgement in the commit message accordingly.
>
> If the consensus (or Junio's decision when applying) is that we don't
> need it, I don't mind if my suggestion is scrapped (or reworded).
I think your clarification is a good addition.
--
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/
^ permalink raw reply
* Re: [PATCH 0/3] Generalized "string function" syntax
From: René Scharfe @ 2009-10-18 8:24 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v63ad5o8p.fsf@alter.siamese.dyndns.org>
Junio C Hamano schrieb:
> René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:
>
>> Junio C Hamano schrieb:
>>> I mentioned an idea to enhance the pretty=format language with a
>>> string function syntax that people can extend by adding new functions
>>> in one of the "What's cooking" messages earlier. The general syntax
>>> would be like
>>>
>>> %[function(args...)any string here%]
>>>
>>> where "any string here" part would have the usual pretty=format
>>> strings. E.g. git show -s --format='%{w(72,8,4)%s%+b%]' should give
>>> you a line wrapped commit log message if w(width,in1,in2) is such a
>>> function.
>> I pondered line wrapping with format strings briefly a long time ago, and
>> I always considered it to be more similar to a colour, i.e. a state that
>> one can change and that is applied to all following text until the next
>> state change. (Except that it's always reset at the end of the format
>> string.) The example above would then turn into '%w(72,8,4)%s%+b'.
>
> As a syntax to express "wrapping" behaviour alone, I think this is much
> simpler and more superiour. I guess with this if you want to wrap
> something to 72 columns and then wrap something else to 66 columns, you
> would write '%w(72,8,4)something%w(66,8,4)something else', right?
That's right.
> I used %] only for two reasons.
>
> - Without an explicit "here it ends", I couldn't come up with a good way
> to express '%[w(72,8,4)something%]something else'. IOW, how I can say
> "wrap something to 72 columns and then place something else without any
> wrapping"?
My patch makes '%w()' reset the wrapping parameters to their defaults.
> - When we need to support more than one string function like this, it is
> unclear what '%f()one string%g()another one' in your syntax means.
> Does it mean '%[f()one string%]%[g()another one%]' (i.e. concatenate
> the result of applying string function f to 'one string' and the result
> of applying string function g to 'another one')? Or does it mean
> '%[f()one string%[g()another one%]%]' (apply 'f' to concatenation of
> 'one string' and the result of applying 'g' to 'another one')?
I was going to say that we already have something like that with %C, and
that the natural way (to me) is to apply them both, independently. Case
modification functions (upper, lower, capitalized) could be treated the
same way -- as state changes (like pressing caps lock when typing text).
Which other text functions are we going to add which would break this
model? The only thing I can think of right now is nesting such
functions themselves, e.g. when indenting a list in an indented
sub-paragraph in an indented paragraph. Useful?
But then something else hit me: the line wrap function needs to consider
colour codes as having a length of zero. Ugh.
René
^ permalink raw reply
* [PATCH 3/3] git checkout --nodwim
From: Junio C Hamano @ 2009-10-18 8:01 UTC (permalink / raw)
To: git; +Cc: Johannes Schindelin, Jay Soffian
In-Reply-To: <7vzl7pyvzl.fsf@alter.siamese.dyndns.org>
Porcelains may want to make sure their calls to "git checkout" will
reliably fail regardless of the presense of random remote tracking
branches by the new DWIMmery introduced.
Luckily all existing in-tree callers have extra checks to make sure they
feed local branch name when they want to switch, or they explicitly ask
to detach HEAD at the given commit, so there is no need to add this option
for them.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin-checkout.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/builtin-checkout.c b/builtin-checkout.c
index fb7e68a..6ec9b83 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -616,6 +616,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
struct tree *source_tree = NULL;
char *conflict_style = NULL;
int patch_mode = 0;
+ int dwim_new_local_branch = 1;
struct option options[] = {
OPT__QUIET(&opts.quiet),
OPT_STRING('b', NULL, &opts.new_branch, "new branch", "branch"),
@@ -631,6 +632,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
OPT_STRING(0, "conflict", &conflict_style, "style",
"conflict style (merge or diff3)"),
OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"),
+ OPT_SET_INT(0, "nodwim", &dwim_new_local_branch,
+ "do not dwim local branch creation", 0),
OPT_END(),
};
int has_dash_dash;
@@ -715,6 +718,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
if (has_dash_dash) /* case (1) */
die("invalid reference: %s", arg);
if (!patch_mode &&
+ dwim_new_local_branch &&
opts.track == BRANCH_TRACK_UNSPECIFIED &&
!opts.new_branch &&
!check_filename(NULL, arg) &&
--
1.6.5.1.95.g09fbd
^ permalink raw reply related
* [PATCH 2/3] DWIM "git checkout frotz" to "git checkout -b frotz origin/frotz"
From: Junio C Hamano @ 2009-10-18 8:01 UTC (permalink / raw)
To: git; +Cc: Johannes Schindelin, Jay Soffian
In-Reply-To: <7vzl7pyvzl.fsf@alter.siamese.dyndns.org>
When 'frotz' is not a valid object name nor a tracked filename,
we used to complain and failed this command. When there is only
one remote that has 'frotz' as one of its tracking branches, we can
DWIM it as a request to create a local branch 'frotz' forking from
the matching remote tracking branch.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin-checkout.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 57 insertions(+), 3 deletions(-)
diff --git a/builtin-checkout.c b/builtin-checkout.c
index d050c37..fb7e68a 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -572,6 +572,40 @@ static int interactive_checkout(const char *revision, const char **pathspec,
return run_add_interactive(revision, "--patch=checkout", pathspec);
}
+struct tracking_name_data {
+ const char *name;
+ char *remote;
+ int unique;
+};
+
+static int check_tracking_name(const char *refname, const unsigned char *sha1,
+ int flags, void *cb_data)
+{
+ struct tracking_name_data *cb = cb_data;
+ const char *slash;
+
+ if (prefixcmp(refname, "refs/remotes/"))
+ return 0;
+ slash = strchr(refname + 13, '/');
+ if (!slash || strcmp(slash + 1, cb->name))
+ return 0;
+ if (cb->remote) {
+ cb->unique = 0;
+ return 0;
+ }
+ cb->remote = xstrdup(refname);
+ return 0;
+}
+
+static const char *unique_tracking_name(const char *name)
+{
+ struct tracking_name_data cb_data = { name, NULL, 1 };
+ for_each_ref(check_tracking_name, &cb_data);
+ if (cb_data.unique)
+ return cb_data.remote;
+ free(cb_data.remote);
+ return NULL;
+}
int cmd_checkout(int argc, const char **argv, const char *prefix)
{
@@ -630,8 +664,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
opts.new_branch = argv0 + 1;
}
- if (opts.track == BRANCH_TRACK_UNSPECIFIED)
- opts.track = git_branch_track;
if (conflict_style) {
opts.merge = 1; /* implied */
git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
@@ -655,6 +687,11 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
* With no paths, if <something> is a commit, that is to
* switch to the branch or detach HEAD at it.
*
+ * With no paths, if <something> is _not_ a commit, no -t nor -b
+ * was given, and there is a tracking branch whose name is
+ * <something> in one and only one remote, then this is a short-hand
+ * to fork local <something> from that remote tracking branch.
+ *
* Otherwise <something> shall not be ambiguous.
* - If it's *only* a reference, treat it like case (1).
* - If it's only a path, treat it like case (2).
@@ -677,7 +714,20 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
if (get_sha1(arg, rev)) {
if (has_dash_dash) /* case (1) */
die("invalid reference: %s", arg);
- goto no_reference; /* case (3 -> 2) */
+ if (!patch_mode &&
+ opts.track == BRANCH_TRACK_UNSPECIFIED &&
+ !opts.new_branch &&
+ !check_filename(NULL, arg) &&
+ argc == 1) {
+ const char *remote = unique_tracking_name(arg);
+ if (!remote || get_sha1(remote, rev))
+ goto no_reference;
+ opts.new_branch = arg;
+ arg = remote;
+ /* DWIMmed to create local branch */
+ }
+ else
+ goto no_reference;
}
/* we can't end up being in (2) anymore, eat the argument */
@@ -715,6 +765,10 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
}
no_reference:
+
+ if (opts.track == BRANCH_TRACK_UNSPECIFIED)
+ opts.track = git_branch_track;
+
if (argc) {
const char **pathspec = get_pathspec(prefix, argv);
--
1.6.5.1.95.g09fbd
^ permalink raw reply related
* [PATCH 1/3] check_filename(): make verify_filename() callable without dying
From: Junio C Hamano @ 2009-10-18 8:00 UTC (permalink / raw)
To: git; +Cc: Johannes Schindelin, Jay Soffian
In-Reply-To: <7vzl7pyvzl.fsf@alter.siamese.dyndns.org>
Make it possible to invole the logic of verify_filename() to make sure the
pathname arguments are unambiguous without actually dying. The caller may
want to do something different.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
cache.h | 1 +
setup.c | 38 ++++++++++++++++++++------------------
2 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/cache.h b/cache.h
index 96840c7..71a731d 100644
--- a/cache.h
+++ b/cache.h
@@ -396,6 +396,7 @@ extern const char *setup_git_directory_gently(int *);
extern const char *setup_git_directory(void);
extern const char *prefix_path(const char *prefix, int len, const char *path);
extern const char *prefix_filename(const char *prefix, int len, const char *path);
+extern int check_filename(const char *prefix, const char *name);
extern void verify_filename(const char *prefix, const char *name);
extern void verify_non_filename(const char *prefix, const char *name);
diff --git a/setup.c b/setup.c
index 029371e..f67250b 100644
--- a/setup.c
+++ b/setup.c
@@ -61,6 +61,19 @@ const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
return path;
}
+int check_filename(const char *prefix, const char *arg)
+{
+ const char *name;
+ struct stat st;
+
+ name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg;
+ if (!lstat(name, &st))
+ return 1; /* file exists */
+ if (errno == ENOENT || errno == ENOTDIR)
+ return 0; /* file does not exist */
+ die_errno("failed to stat '%s'", arg);
+}
+
/*
* Verify a filename that we got as an argument for a pathspec
* entry. Note that a filename that begins with "-" never verifies
@@ -70,18 +83,12 @@ const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
*/
void verify_filename(const char *prefix, const char *arg)
{
- const char *name;
- struct stat st;
-
if (*arg == '-')
die("bad flag '%s' used after filename", arg);
- name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg;
- if (!lstat(name, &st))
+ if (check_filename(prefix, arg))
return;
- if (errno == ENOENT)
- die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
- "Use '--' to separate paths from revisions", arg);
- die_errno("failed to stat '%s'", arg);
+ die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
+ "Use '--' to separate paths from revisions", arg);
}
/*
@@ -91,19 +98,14 @@ void verify_filename(const char *prefix, const char *arg)
*/
void verify_non_filename(const char *prefix, const char *arg)
{
- const char *name;
- struct stat st;
-
if (!is_inside_work_tree() || is_inside_git_dir())
return;
if (*arg == '-')
return; /* flag */
- name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg;
- if (!lstat(name, &st))
- die("ambiguous argument '%s': both revision and filename\n"
- "Use '--' to separate filenames from revisions", arg);
- if (errno != ENOENT && errno != ENOTDIR)
- die_errno("failed to stat '%s'", arg);
+ if (!check_filename(prefix, arg))
+ return;
+ die("ambiguous argument '%s': both revision and filename\n"
+ "Use '--' to separate filenames from revisions", arg);
}
const char **get_pathspec(const char *prefix, const char **pathspec)
--
1.6.5.1.95.g09fbd
^ permalink raw reply related
* Re: [PATCH/RFC] builtin-checkout: suggest creating local branch when appropriate to do so
From: Junio C Hamano @ 2009-10-18 7:58 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Jay Soffian, git
In-Reply-To: <alpine.DEB.1.00.0910052314580.4985@pacific.mpi-cbg.de>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> Actually, we should really think long and hard why we should not
> automatically check out the local branch "next" in that case.
While people were thinking long and hard, I've spent some quality time
having fun with these patches, and realized that if we limit the scope of
the change to make sure that we only change the behaviour of a case where
we refused to do anything, this is not even something we need to think
long nor hard after all.
At least from the maintainer's point of view, that is.
I on the other hand do agree that we need to think long and hard when it
comes to the matter of explaining this to the users, though. I couldn't
come up with a good (re-)ordering of the documentation to fit this new
"short-cut" into the manpage.
A three-patch series will follow shortly.
^ permalink raw reply
* Re: [PATCH v3.1 3/5] Introduce new pretty formats %g[sdD] for reflog information
From: Jeff King @ 2009-10-18 7:18 UTC (permalink / raw)
To: Thomas Rast; +Cc: Junio C Hamano, Jef Driesen, Nanako Shiraishi, git
In-Reply-To: <e0ab6923eb4057bcbc8e97980dad5e4a37e53067.1255790816.git.trast@student.ethz.ch>
On Sat, Oct 17, 2009 at 04:48:11PM +0200, Thomas Rast wrote:
> > +NOTE: Some placeholders may depend on other options given to the
> > +revision traversal engine. For example, the `%g*` reflog options will
> > +insert an empty string unless we are traversing reflog entries (e.g., by
> > +`git log -g`). The `%d` placeholder will use the "short" decoration
> > +format if `--decorate` was not already provided on the command line.
>
> Sure. I figured it was obvious enough, but since you already went to
> the lengths of documenting the exact behaviour of %d, I squashed it
> and adjusted the acknowledgement in the commit message accordingly.
If the consensus (or Junio's decision when applying) is that we don't
need it, I don't mind if my suggestion is scrapped (or reworded).
-Peff
^ permalink raw reply
* Re: [PATCH 0/3] Generalized "string function" syntax
From: Junio C Hamano @ 2009-10-18 4:18 UTC (permalink / raw)
To: René Scharfe; +Cc: git
In-Reply-To: <4ADA3153.7070606@lsrfire.ath.cx>
René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:
> Junio C Hamano schrieb:
>> I mentioned an idea to enhance the pretty=format language with a
>> string function syntax that people can extend by adding new functions
>> in one of the "What's cooking" messages earlier. The general syntax
>> would be like
>>
>> %[function(args...)any string here%]
>>
>> where "any string here" part would have the usual pretty=format
>> strings. E.g. git show -s --format='%{w(72,8,4)%s%+b%]' should give
>> you a line wrapped commit log message if w(width,in1,in2) is such a
>> function.
>
> I pondered line wrapping with format strings briefly a long time ago, and
> I always considered it to be more similar to a colour, i.e. a state that
> one can change and that is applied to all following text until the next
> state change. (Except that it's always reset at the end of the format
> string.) The example above would then turn into '%w(72,8,4)%s%+b'.
As a syntax to express "wrapping" behaviour alone, I think this is much
simpler and more superiour. I guess with this if you want to wrap
something to 72 columns and then wrap something else to 66 columns, you
would write '%w(72,8,4)something%w(66,8,4)something else', right?
I used %] only for two reasons.
- Without an explicit "here it ends", I couldn't come up with a good way
to express '%[w(72,8,4)something%]something else'. IOW, how I can say
"wrap something to 72 columns and then place something else without any
wrapping"?
- When we need to support more than one string function like this, it is
unclear what '%f()one string%g()another one' in your syntax means.
Does it mean '%[f()one string%]%[g()another one%]' (i.e. concatenate
the result of applying string function f to 'one string' and the result
of applying string function g to 'another one')? Or does it mean
'%[f()one string%[g()another one%]%]' (apply 'f' to concatenation of
'one string' and the result of applying 'g' to 'another one')?
^ permalink raw reply
* How to revert one of multiple merges
From: Bill Lear @ 2009-10-18 2:31 UTC (permalink / raw)
To: git
Branch A, B, C each have 20 commits, 0-19.
Branch v1.0.0 created, then merge of A, B, C performed.
After testing, we realize that the branch B is not ready for
production release and we'd like to remove it from branch
v1.0.0.
If I do
% git merge A B C
I get a single commit:
% git log -p
commit 1644a0b98c01869aa83e59aa41374c22098c47b6
[...]
Date: Fri Oct 16 09:52:32 2009 -0500
Merge branches 'A', 'B' and 'C' into v1.0.0
[20 x 3 commits]
If I do
% git merge A
% git merge B
% git merge C
Then:
% git log -p
commit 8946edd381384d0882221c87b5b3b7bf47127d70
[...]
Date: Sat Oct 17 21:28:36 2009 -0500
Merge branch 'B' into v1.0.0
commit 076ed422443e3684e564f7cae2b92e4538088ae6
[...]
Date: Sat Oct 17 21:28:35 2009 -0500
Merge branch 'A' into v1.0.0
but no "Merge branch 'C' into v1.0.0".
And so, I'm faced with git rebase -i posing some unanswerable questions
to our release manager. She cannot easily remove B from the merge after
doint either merge A B C, or merge A, merge B, merge C.
Can anyone help?
Bill
^ permalink raw reply
* [ANNOUNCE] GIT 1.6.5.1
From: Junio C Hamano @ 2009-10-18 1:04 UTC (permalink / raw)
To: git
The latest maintenance release GIT 1.6.5.1 is available at the
usual places:
http://www.kernel.org/pub/software/scm/git/
git-1.6.5.1.tar.{gz,bz2} (source tarball)
git-htmldocs-1.6.5.1.tar.{gz,bz2} (preformatted docs)
git-manpages-1.6.5.1.tar.{gz,bz2} (preformatted docs)
The RPM binary packages for a few architectures are found in:
RPMS/$arch/git-*-1.6.5.1-1.fc9.$arch.rpm (RPM)
GIT v1.6.5.1 Release Notes
==========================
Fixes since v1.6.5
------------------
* An corrupt pack could make codepath to read objects into an
infinite loop.
* Download throughput display was always shown in KiB/s but on fast links
it is more appropriate to show it in MiB/s.
* "git grep -f filename" used uninitialized variable and segfaulted.
* "git clone -b branch" gave a wrong commit object name to post-checkout
hook.
* "git pull" over http did not work on msys.
Other minor documentation updates are included.
----------------------------------------------------------------
Changes since v1.6.5 are as follows:
Björn Steinbrink (1):
clone: Supply the right commit hash to post-checkout when -b is used
Johannes Sixt (1):
remote-curl: add missing initialization of argv0_path
Junio C Hamano (1):
GIT 1.6.5.1
Matt Kraai (1):
grep: do not segfault when -f is used
Miklos Vajna (1):
git-stash documentation: mention default options for 'list'
Nicolas Pitre (1):
change throughput display units with fast links
Shawn O. Pearce (1):
sha1_file: Fix infinite loop when pack is corrupted
^ permalink raw reply
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Julian Phillips @ 2009-10-17 22:28 UTC (permalink / raw)
To: Björn Steinbrink
Cc: Nicolas Pitre, Junio C Hamano, Daniel Barkalow, James Pickens,
Jeff King, Jay Soffian, Git Mailing List
In-Reply-To: <20091017174843.GA16251@atjola.homenet>
On Sat, 17 Oct 2009, Bj?rn Steinbrink wrote:
> On 2009.10.17 18:35:38 +0100, Julian Phillips wrote:
>> On Sat, 17 Oct 2009, Bj?rn Steinbrink wrote:
>>> Do you have multiple (annotated) tags for the same commit?
>>
>> Potentially, yes. Releasing isn't the only thing that requires
>> keeping track of things. It's even possible that the person
>> creating the newer tag doesn't yet know that a release tag has been
>> applied if the person who applied it hasn't yet pushed it back.
>
> OK, I'd consider that namespace pollution, as things like
> "this-version-sucks" doesn't seem like it show go into public repos, but
> anyway. If your release tags fix into a certain "unique" format, you
> could use describe with --match, like:
> git describe --match 'v[0-9]*'
Well - that only helps if we only ever build the release tags. Which
isn't the case. The other tags are there for similar purposes and also
should go into the version string - but only when they were the tag
checked out.
Is it really that unreasonable to want to know exactly what it was that
was checked out? It's one of the few things that I miss from Subversion.
--
Julian
---
printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled :-)\n");
linux-2.6.6/drivers/message/fusion/mptbase.c
^ permalink raw reply
* Re: git submodules
From: Nanako Shiraishi @ 2009-10-17 22:30 UTC (permalink / raw)
To: Jakub Narebski; +Cc: Git Mailing List, Steven Noonan, crawl-ref-discuss
In-Reply-To: <m3tyxydj8f.fsf@localhost.localdomain>
Quoting Jakub Narebski <jnareb@gmail.com>
> Steven Noonan <steven@uplinklabs.net> writes:
>
>> We're using git submodules for the contributing libraries. When I
>> commit changes to those contribs, it correctly shows in the parent
>> repository that those folders have different revisions than what's
>> currently committed. However, if someone pulls those changes, it
>> doesn't automatically update the contribs to match the committed
>> version. But doing a pull or merge _should_ update the working tree to
>> match the committed versions. It does with file data, so why not
>> update the submodules? Especially if the submodule revision matched
>> the committed version -before- the pull. Why are we forced into using
>> 'git submodule update'?
>
> Because you might want not to use most current version of submodule,
> so git-pull shouldn't update submodules by default. And because
> git-pull didn't learn --recursive option yet.
I don't think your description is correct. Steven is talking about what the command should do by default. If you checked out the current superproject, by default you should get the submodule that matches. If you don't want the most current version, you can checkout an older submodule yourself.
You may want to follow this discussion:
http://thread.gmane.org/gmane.comp.version-control.git/130155/focus=130330
After stating that he isn't against the idea to make it automatic, Junio describes what needs to be done for it to happen and what are the corner cases that needs to be treated with care.
--
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/
^ permalink raw reply
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Julian Phillips @ 2009-10-17 22:19 UTC (permalink / raw)
To: Junio C Hamano
Cc: Björn Steinbrink, Daniel Barkalow, James Pickens, Jeff King,
Nicolas Pitre, Jay Soffian, git
In-Reply-To: <7vljj97w7u.fsf@alter.siamese.dyndns.org>
On Sat, 17 Oct 2009, Junio C Hamano wrote:
> Julian Phillips <julian@quantumfyre.co.uk> writes:
>
>>>> My interest in this thread is solely that it might provide a mechanism
>>>> to find out which tag was checked out.
>>>
>>> Hmm, what is lacking in "git describe HEAD" for that? I am not
>>> complaining that you might be asking for something that exists, but I _do_
>>> want to know if something that exists is not a satisfactory solution and
>>> if so how it can be improved.
>>
>> What is lacking is the "checked out" part. "git describe HEAD" will
>> tell me _a_ tag that matches the currently checked out state.
>> However, it makes no guarantee that it was the one I checked out. If
>> I tag the code with "v1.0.0", and a colleague later tags it with
>> "this_version_sucks", then when I check out and build the code for the
>> customer the version it reports could well be "this_version_sucks"
>> instead of "v1.0.0" ...
>
> I think I understand why you think showing what you gave to your last "git
> checkout" (e.g. "checkout origin/master" or "checkout v1.0.0") and using
> that as a build identification token is a good idea. But "origin/master"
> is a moving target---it depends on when you checked it out. describe uses
> tags and does not use branch heads for a good reason.
For my purposes the branch that I built from is much more useful than the
output from describe. Releases are always made from tags, but for builds
used in the lab it is generally much more useful to know which branch was
built directly rather than being able to find the exact commit that was
built.
> "v1.0.0" also is to a lessor degree, as you may have tagged v1.0.0 locally
> and somebody else also has used the tag for a different version, but a tag
> is far less likely to move due to social convention. "describe --long"
> would make sure this won't be an issue anyway, though.
For any particular release only one person is given the job of making the
release tag, so we don't have the problem of multiple instances of the
same tag - but we do need to make sure that the version output is the
correct tag.
--
Julian
---
Water, taken in moderation cannot hurt anybody.
-- Mark Twain
^ permalink raw reply
* Re: [PATCH 1/3] format_commit_message(): fix function signature
From: René Scharfe @ 2009-10-17 21:04 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <1255681702-5215-2-git-send-email-gitster@pobox.com>
Junio C Hamano schrieb:
> The format template string was declared as "const void *" for some unknown
> reason, even though it obviously is meant to be passed a string. Make it
> "const char *".
Yes. I seem to have introduced that type in commit 7b95089c, but I
can't see (even less remember) why. Also note that commit message and
header file call the parameter "template", while it's called "format" in
commit.c (where the function used to live back then). What was I thinking?
Thanks for cleaning up after me.
René
^ permalink raw reply
* Re: [PATCH 0/3] Generalized "string function" syntax
From: René Scharfe @ 2009-10-17 21:04 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <1255681702-5215-1-git-send-email-gitster@pobox.com>
Junio C Hamano schrieb:
> I mentioned an idea to enhance the pretty=format language with a
> string function syntax that people can extend by adding new functions
> in one of the "What's cooking" messages earlier. The general syntax
> would be like
>
> %[function(args...)any string here%]
>
> where "any string here" part would have the usual pretty=format
> strings. E.g. git show -s --format='%{w(72,8,4)%s%+b%]' should give
> you a line wrapped commit log message if w(width,in1,in2) is such a
> function.
I pondered line wrapping with format strings briefly a long time ago, and
I always considered it to be more similar to a colour, i.e. a state that
one can change and that is applied to all following text until the next
state change. (Except that it's always reset at the end of the format
string.) The example above would then turn into '%w(72,8,4)%s%+b'.
Here's a patch to implement this behaviour. It leaves the implementation
of the actual wrap function as an exercise to the reader, too. ;-)
pretty.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/pretty.c b/pretty.c
index f5983f8..33464f1 100644
--- a/pretty.c
+++ b/pretty.c
@@ -445,6 +445,7 @@ struct format_commit_context {
enum date_mode dmode;
unsigned commit_header_parsed:1;
unsigned commit_message_parsed:1;
+ size_t width, indent1, indent2;
/* These offsets are relative to the start of the commit message. */
struct chunk author;
@@ -458,6 +459,7 @@ struct format_commit_context {
struct chunk abbrev_commit_hash;
struct chunk abbrev_tree_hash;
struct chunk abbrev_parent_hashes;
+ size_t wrap_start;
};
static int add_again(struct strbuf *sb, struct chunk *chunk)
@@ -595,6 +597,44 @@ static void format_decoration(struct strbuf *sb, const struct commit *commit)
strbuf_addch(sb, ')');
}
+static void strbuf_wrap(struct strbuf *sb, size_t pos, size_t len,
+ size_t width, size_t indent1, size_t indent2)
+{
+ struct strbuf tmp = STRBUF_INIT;
+
+ if (!len)
+ return;
+ if (pos)
+ strbuf_add(&tmp, sb->buf, pos);
+
+ /* XXX: all that's missing is the wrapping code itself.. */
+ strbuf_addf(&tmp, "w(%u,%u,%u)[\n",
+ (unsigned)width, (unsigned)indent1, (unsigned)indent2);
+ strbuf_add(&tmp, sb->buf + pos, len);
+ strbuf_addstr(&tmp, "\n]");
+
+ if (pos + len < sb->len)
+ strbuf_add(&tmp, sb->buf + pos + len, sb->len - pos - len);
+ strbuf_swap(&tmp, sb);
+ strbuf_release(&tmp);
+}
+
+static void rewrap_message_tail(struct strbuf *sb,
+ struct format_commit_context *c,
+ size_t new_width, size_t new_indent1,
+ size_t new_indent2)
+{
+ if (c->width == new_width && c->indent1 == new_indent1 &&
+ c->indent2 == new_indent2)
+ return;
+ strbuf_wrap(sb, c->wrap_start, sb->len - c->wrap_start, c->width,
+ c->indent1, c->indent2);
+ c->wrap_start = sb->len;
+ c->width = new_width;
+ c->indent1 = new_indent1;
+ c->indent2 = new_indent2;
+}
+
static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
void *context)
{
@@ -645,6 +685,30 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
return 3;
} else
return 0;
+ case 'w':
+ if (placeholder[1] == '(') {
+ unsigned long width = 0, indent1 = 0, indent2 = 0;
+ char *next;
+ const char *start = placeholder + 2;
+ const char *end = strchr(start, ')');
+ if (!end)
+ return 0;
+ if (end > start) {
+ width = strtoul(start, &next, 10);
+ if (*next == ',') {
+ indent1 = strtoul(next + 1, &next, 10);
+ if (*next == ',') {
+ indent2 = strtoul(next + 1,
+ &next, 10);
+ }
+ }
+ if (*next != ')')
+ return 0;
+ }
+ rewrap_message_tail(sb, c, width, indent1, indent2);
+ return end - placeholder + 1;
+ } else
+ return 0;
}
/* these depend on the commit */
@@ -748,7 +812,9 @@ void format_commit_message(const struct commit *commit,
memset(&context, 0, sizeof(context));
context.commit = commit;
context.dmode = dmode;
+ context.wrap_start = sb->len;
strbuf_expand(sb, format, format_commit_item, &context);
+ rewrap_message_tail(sb, &context, 0, 0, 0);
}
static void pp_header(enum cmit_fmt fmt,
^ permalink raw reply related
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Daniel Barkalow @ 2009-10-17 20:35 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Christoph Bartoschek, git
In-Reply-To: <7vr5t2h3do.fsf@alter.siamese.dyndns.org>
On Sat, 17 Oct 2009, Junio C Hamano wrote:
> Christoph Bartoschek <bartoschek@gmx.de> writes:
>
> [jc: added Daniel back to cc list; please do not cull the cc list without
> good reason]
>
> > Daniel Barkalow wrote:
> >
> >> The upshot of the messages should be:
> >>
> >> $ git checkout origin/master
> >> Since you can't actually change "origin/master" yourself, you'll just
> >> be sightseeing unless you create a local branch to hold new local work.
> >>
> >> $ git branch
> >> * (not a local branch, but "origin/master")
> >>
> >> $ git commit
> >> You've been sightseeing "origin/master". The commit can't change that
> >> value, so your commit isn't held in any branch. If you want to create
> >> a branch to hold it, here's how.
> > ...
> > But then I was not able to verify that the checkout indeed matched the
> > 1.3.0-beta. "git status" and "git branch" did not help here.
>
> This is not going to help you, but "git reflog" would have helped here.
>
> The reason my suggesting "git reflog" now won't help you is because the
> word "reflog" does not connect the question "how did I get here" unless
> and until you know git already; in other words, it is not your fault that
> you got lost, but it is showing a wart in the UI.
>
> If the question you were asking was "does the files I have in my work tree
> after issuing that scary checkout actually match origin/1.3.0-beta?", you
> could have asked that question in a more direct way, and the command to do
> so is "git diff origin/1.3.0-beta". I do not think this would be asking
> the user to be doing something unreasonably unintuitive.
>
> If the question you were asking was (and it was not, from the description
> of your experience, but you could be in that situation when you "return
> some weeks later") "how does the checked out history relate to 1.3.0-beta?",
> then there is a way to ask the question in a very direct way, and the
> command to do so is "git show-branch HEAD origin/1.3.0-beta" (or give the
> same argument to "gitk").
>
> Although it is not _so_ unreasonable to expect "git status" to show the
> information, I suspect it would not be practical. After all, whenever
> somebody is lost, everything is "status". For a person who is lost and
> does not know where in the history he is, it might be reasonable to expect
> "status" to give the relationship between your HEAD and some branch/tag,
> while for another person who was hit by "git gui" complaining that he has
> too many loose objects, it might be reasonable for him to expect "status"
> to give the number of loose objects in the repository. IOW, "status" is
> too broad a word and following the path to cram everything into "status"
> so that any new person who gets lost can get necessary infor from the
> command will unfortunately lead to insanity.
>
> The second item in the Daniel's transcript above may be an improvement but
> I think it is a wrong economy to record and show 'but "origin/master"'
> (which cannot be correct forever and has to be invalidated once the user
> starts committing or resetting) in the message.
It's easy to invalidate it for reasons of the user going elsewhere: you
invalidate it when you invalidate MERGE_HEAD (which, incidentally,
locates a bug in my original patch: there's a third
"unlink(git_path("MERGE_HEAD"));" I didn't think of, in builtin-merge.c).
I think the case of it going stale, mainly due to updating a ref it uses,
is a matter of having whatever wants to describe HEAD check if the
extended sha1 still expands to the same sha1.
I also think that it fits with the git world model to distinguish
"lvalues" from "non-lvalues". An "lvalue" is something where you can make
a commit and change the value while the expression stays the same; you can
assign to it. If your current position is not an "lvalue" and you commit,
your current position must become a new temporary "lvalue", diverging from
the thing you can't change. But if you don't assign to it, there's no
problem with having a non-lvalue be your current position.
> I am wondering if a similar effect to help new users can be had by
> rewording the message to:
>
> $ git branch
> * (not a local branch; see "git reflog" to learn how you got here)
>
> The user can see how he got there even after doing something else after
> the checkout (see Nico's write-up in $gmane/130527). The difference is
> between giving fish and teaching how to catch one himself.
The reflog hint is a good one in general; on the other hand, I think it
would be generally helpful to have the information in a more
machine-readable fashion, for a "git checkout (whatever I gave to reset or
checkout before)".
Perhaps the right implementation is actually to have machine-readable
descriptions in the HEAD reflog? That would actually lead to the
interesting:
$ git checkout topic
$ git checkout origin/master
$ git checkout HEAD@{1}
$ git branch
* topic
Actually, we turn out to have a flaw in our reflog explanation: when
rebase finishes, it doesn't log that it's back to a particular branch.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Björn Steinbrink @ 2009-10-17 19:41 UTC (permalink / raw)
To: Junio C Hamano
Cc: Julian Phillips, Daniel Barkalow, James Pickens, Jeff King,
Nicolas Pitre, Jay Soffian, git
In-Reply-To: <7vaazqcry5.fsf@alter.siamese.dyndns.org>
On 2009.10.17 02:04:02 -0700, Junio C Hamano wrote:
> The "save" part of the work-save-then-merge sequence should be made very
> visible to help people get used to the "not up, but work-save-then-merge"
> mental model. I do not think it would help people in the long run to make
> the "save" step less visible by wrapping the sequence into an unreliable
> "up" script, especially because the script would sometimes work but other
> times *has to* force users to know that what is happening behind the scene
> is work-save-then-merge in order to resolve and recover from conflicts
> anyway.
Hm, which cases would that be? I basically see three cases:
1) No uncommitted changes => No problem
2) Uncommitted changes merge cleanly => No problem
3) Uncommitted changes causes conflicts =>
- User can resolve
- User can start over (git update --retry)
- User can give up (git update --abort)
Of course the user can clearly see that some state was saved (otherwise
you couldn't retry or abort), but I don't see how the user is "forced"
in any way, he just gets those two commands to work with (which
internally just wrap reset + stash apply, making things more
convenient).
I do see problems with a "stash around merge" thing ("stash" around
rebase seems easier, as that could just create a commit and reset later,
but I'm not exactly sure that such smartness is a good idea). As soon as
the merge has conflicts, you need to know that you have to unstash after
committing the merge, but what I have in mind is fast-forward only (or
possibly reset, when upstream was rewritten). Primarily for users that
don't commit at all, but just look at things [*1*]. And also for the
semi-detached HEAD case, in which you may not commit and in which doing
a merge/rebase is therefore not an option, but git still knows what to
fetch/checkout by using the discussed extra info in HEAD, or by
examining the reflog.
> > OTOH, it might be easier to just tell the user to do the stash thing
> > himself. But I wonder how many users would really know how to get back
> > to the initial state then.
>
> I agree with the first sentence, but I do not understand what "the initial
> state" you talk about here in the second sentence, sorry.
The state they were in before they did the "git stash" part.
*work on stuff not ready to be committed*
git pull # refused
git stash
git pull
git stash apply # Conflicts, user decides that he wants go back
At that point, you need the reflog (also handle fast-forwards), and do:
git reset --hard HEAD@{1}
git stash apply --index
Of course, a more correct way might be to use commit and rebase instead:
*work on stuff not ready to be committed*
git pull # refused
git add -A # Or whatever
git commit
git pull --rebase # conflicts, decide to abort
git rebase --abort
git reset HEAD^
But that still needs the extra "reset HEAD^" step to really get back to
the state with your uncommitted changes.
The problem with "svn up" is that there's no other way, and no way back.
Git has other ways, but no convenient one for non-committers and no
"obvious" way to go back, should you decide that you actually prefer not
to update after seeing the conflicts.
Anyway, this isn't _my_ itch and to some (large) degree I'm trying to
guess what someone else would expect. If at all, I'm more interested in
a command that figures out which remote tracking branch I checked out,
and that updates it, and updates my work tree/index as well. Uncommitted
changes aren't important to me there. So I'll simply give up on that
part.
Björn
[*1*] One could also say: Users that don't give a damn about git, but
just need it to get the code and maybe have some minor, uncommitted
modifications on top. I'm _not_ thinking about users that actually
commit and do stuff. Those should use merge/rebase/pull, and get a
complaint from "git update" if the update is not a fast-forward one,
telling them what to use instead.
^ permalink raw reply
* [PATCH] Add the --submodule option to the diff option family
From: Jens Lehmann @ 2009-10-17 18:46 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Schindelin, Git Mailing List
When you use the option --submodule=left-right-log you can see the submodule
summaries inlined in the diff, instead of not-quite-helpful SHA-1 pairs.
The format imitates what "git submodule summary" shows.
To do that, <path>/.git/objects/ is added to the alternate object
databases (if that directory exists).
This option was requested by Jens Lehmann at the GitTogether in Berlin.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
---
In this patch i tried to address all the issues mentioned so far, please
let me know if anything is missing.
Documentation/diff-options.txt | 7 +++
Makefile | 2 +
diff.c | 16 ++++++
diff.h | 1 +
submodule.c | 112 ++++++++++++++++++++++++++++++++++++++++
submodule.h | 8 +++
6 files changed, 146 insertions(+), 0 deletions(-)
create mode 100644 submodule.c
create mode 100644 submodule.h
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 9276fae..99cb517 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -87,6 +87,13 @@ endif::git-format-patch[]
Show only names and status of changed files. See the description
of the `--diff-filter` option on what the status letters mean.
+--submodule[=<format>]::
+ Chose the output format for submodule differences. <format> can be one of
+ 'short' and 'left-right-log'. 'short' is the default value for this
+ option and and shows pairs of commit names. 'left-right-log' lists the
+ commits in that commit range like the 'summary' option of
+ linkgit:git-submodule[1] does.
+
--color::
Show colored diff.
diff --git a/Makefile b/Makefile
index c0eff64..2f61e17 100644
--- a/Makefile
+++ b/Makefile
@@ -453,6 +453,7 @@ LIB_H += sideband.h
LIB_H += sigchain.h
LIB_H += strbuf.h
LIB_H += string-list.h
+LIB_H += submodule.h
LIB_H += tag.h
LIB_H += transport.h
LIB_H += tree.h
@@ -551,6 +552,7 @@ LIB_OBJS += sideband.o
LIB_OBJS += sigchain.o
LIB_OBJS += strbuf.o
LIB_OBJS += string-list.o
+LIB_OBJS += submodule.o
LIB_OBJS += symlinks.o
LIB_OBJS += tag.o
LIB_OBJS += trace.o
diff --git a/diff.c b/diff.c
index c719ce2..8af1ae2 100644
--- a/diff.c
+++ b/diff.c
@@ -13,6 +13,7 @@
#include "utf8.h"
#include "userdiff.h"
#include "sigchain.h"
+#include "submodule.h"
#ifdef NO_FAST_WORKING_DIRECTORY
#define FAST_WORKING_DIRECTORY 0
@@ -1557,6 +1558,17 @@ static void builtin_diff(const char *name_a,
const char *a_prefix, *b_prefix;
const char *textconv_one = NULL, *textconv_two = NULL;
+ if (DIFF_OPT_TST(o, SUBMODULE_LEFT_RIGHT_LOG) &&
+ (!one->mode || S_ISGITLINK(one->mode)) &&
+ (!two->mode || S_ISGITLINK(two->mode))) {
+ const char *del = diff_get_color_opt(o, DIFF_FILE_OLD);
+ const char *add = diff_get_color_opt(o, DIFF_FILE_NEW);
+ show_submodule_summary(o->file, one ? one->path : two->path,
+ one->sha1, two->sha1,
+ del, add, reset);
+ return;
+ }
+
if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
textconv_one = get_textconv(one);
textconv_two = get_textconv(two);
@@ -2771,6 +2783,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
DIFF_OPT_CLR(options, ALLOW_TEXTCONV);
else if (!strcmp(arg, "--ignore-submodules"))
DIFF_OPT_SET(options, IGNORE_SUBMODULES);
+ else if (!prefixcmp(arg, "--submodule=")) {
+ if (!strcmp(arg + 12, "left-right-log"))
+ DIFF_OPT_SET(options, SUBMODULE_LEFT_RIGHT_LOG);
+ }
/* misc options */
else if (!strcmp(arg, "-z"))
diff --git a/diff.h b/diff.h
index a7e7ccb..8079f5b 100644
--- a/diff.h
+++ b/diff.h
@@ -67,6 +67,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
#define DIFF_OPT_DIRSTAT_BY_FILE (1 << 20)
#define DIFF_OPT_ALLOW_TEXTCONV (1 << 21)
#define DIFF_OPT_DIFF_FROM_CONTENTS (1 << 22)
+#define DIFF_OPT_SUBMODULE_LEFT_RIGHT_LOG (1 << 23)
#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)
#define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag)
diff --git a/submodule.c b/submodule.c
new file mode 100644
index 0000000..206386f
--- /dev/null
+++ b/submodule.c
@@ -0,0 +1,112 @@
+#include "cache.h"
+#include "submodule.h"
+#include "dir.h"
+#include "diff.h"
+#include "commit.h"
+#include "revision.h"
+
+int add_submodule_odb(const char *path)
+{
+ struct strbuf objects_directory = STRBUF_INIT;
+ struct alternate_object_database *alt_odb;
+
+ strbuf_addf(&objects_directory, "%s/.git/objects/", path);
+ if (!is_directory(objects_directory.buf))
+ return -1;
+
+ /* avoid adding it twice */
+ for (alt_odb = alt_odb_list; alt_odb; alt_odb = alt_odb->next)
+ if (alt_odb->name - alt_odb->base == objects_directory.len &&
+ !strncmp(alt_odb->base, objects_directory.buf,
+ objects_directory.len))
+ return 0;
+
+ alt_odb = xmalloc(objects_directory.len + 42 + sizeof(*alt_odb));
+ alt_odb->next = alt_odb_list;
+ strcpy(alt_odb->base, objects_directory.buf);
+ alt_odb->name = alt_odb->base + objects_directory.len;
+ alt_odb->name[2] = '/';
+ alt_odb->name[40] = '\0';
+ alt_odb->name[41] = '\0';
+ alt_odb_list = alt_odb;
+ prepare_alt_odb();
+ return 0;
+}
+
+void show_submodule_summary(FILE *f, const char *path,
+ unsigned char one[20], unsigned char two[20],
+ const char *del, const char *add, const char *reset)
+{
+ struct rev_info rev;
+ struct commit *commit, *left = left, *right;
+ struct commit_list *merge_bases, *list;
+ const char *message = NULL;
+ struct strbuf sb = STRBUF_INIT;
+ static const char *format = " %m %s";
+ int fast_forward = 0, fast_backward = 0;
+
+ if (is_null_sha1(two))
+ message = "(submodule deleted)";
+ else if (add_submodule_odb(path))
+ message = "(not checked out)";
+ else if (is_null_sha1(one))
+ message = "(new submodule)";
+ else if (!(left = lookup_commit_reference(one)) ||
+ !(right = lookup_commit_reference(two)))
+ message = "(commits not present)";
+
+ if (!message) {
+ init_revisions(&rev, NULL);
+ setup_revisions(0, NULL, &rev, NULL);
+ rev.left_right = 1;
+ rev.first_parent_only = 1;
+ left->object.flags |= SYMMETRIC_LEFT;
+ add_pending_object(&rev, &left->object, path);
+ add_pending_object(&rev, &right->object, path);
+ merge_bases = get_merge_bases(left, right, 1);
+ if (merge_bases) {
+ if (merge_bases->item == left)
+ fast_forward = 1;
+ else if (merge_bases->item == right)
+ fast_backward = 1;
+ }
+ for (list = merge_bases; list; list = list->next) {
+ list->item->object.flags |= UNINTERESTING;
+ add_pending_object(&rev, &list->item->object,
+ sha1_to_hex(list->item->object.sha1));
+ }
+ if (prepare_revision_walk(&rev))
+ message = "(revision walker failed)";
+ }
+
+ strbuf_addf(&sb, "Submodule %s %s..", path,
+ find_unique_abbrev(one, DEFAULT_ABBREV));
+ if (!fast_backward && !fast_forward)
+ strbuf_addch(&sb, '.');
+ strbuf_addf(&sb, "%s", find_unique_abbrev(two, DEFAULT_ABBREV));
+ if (message)
+ strbuf_addf(&sb, " %s\n", message);
+ else
+ strbuf_addf(&sb, "%s:\n", fast_backward ? " (rewind)" : "");
+ fwrite(sb.buf, sb.len, 1, f);
+
+ if (!message) {
+ while ((commit = get_revision(&rev))) {
+ strbuf_setlen(&sb, 0);
+ if (commit->object.flags & SYMMETRIC_LEFT) {
+ if (del)
+ strbuf_addstr(&sb, del);
+ }
+ else if (add)
+ strbuf_addstr(&sb, add);
+ format_commit_message(commit, format, &sb,
+ rev.date_mode);
+ if (reset)
+ strbuf_addstr(&sb, reset);
+ strbuf_addch(&sb, '\n');
+ fprintf(f, "%s", sb.buf);
+ }
+ clear_commit_marks(left, ~0);
+ clear_commit_marks(right, ~0);
+ }
+}
diff --git a/submodule.h b/submodule.h
new file mode 100644
index 0000000..4c0269d
--- /dev/null
+++ b/submodule.h
@@ -0,0 +1,8 @@
+#ifndef SUBMODULE_H
+#define SUBMODULE_H
+
+void show_submodule_summary(FILE *f, const char *path,
+ unsigned char one[20], unsigned char two[20],
+ const char *del, const char *add, const char *reset);
+
+#endif
--
1.6.5.3.g464e1.dirty
^ permalink raw reply related
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