* Re: [PATCH] user-manual: Use "git config --global" instead of editing ~/.gitconfig
From: Johan Herland @ 2007-05-10 22:16 UTC (permalink / raw)
To: J. Bruce Fields; +Cc: git
In-Reply-To: <20070510220253.GZ13719@fieldses.org>
[-- Attachment #1: Type: text/plain, Size: 1131 bytes --]
On Friday 11 May 2007, J. Bruce Fields wrote:
> On Thu, May 10, 2007 at 11:53:31PM +0200, Johan Herland wrote:
> > Use git-config for setting global user.name and user.email rather than
> > telling the user to edit ~/.gitconfig directly. This brings
> > user-manual.txt in line with tutorial.txt.
>
> The inconsistency is intentional. We want users to know about
> git-config, because it's helpful when writing scripts, and because it
> has a useful manpage. But we also want them to know about the
> config-file syntax, since most of us find reading and editing a file
> more intuitive than running git-config. So we use a mixture of both.
I see your point, but when I look at the user manual, the only place I can
actually find git-config used is in [[remote-branch-configuration]].
Besides, we also present the config-file syntax for user.{name,email} in
[[telling-git-your-name]], so it's not like I'm remove every reference to
the layout of .gitconfig.
Maybe we can present both versions in [[making-changes]]?
Have fun!
...Johan
--
Johan Herland, <johan@herland.net>
www.herland.net
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: Using StGIT for tweaking already-committed stuff
From: Karl Hasselström @ 2007-05-10 22:23 UTC (permalink / raw)
To: Petr Baudis
Cc: Carl Worth, J. Bruce Fields, Linus Torvalds, Johannes Sixt,
catalin.marinas, git
In-Reply-To: <20070510200253.GD4489@pasky.or.cz>
On 2007-05-10 22:02:53 +0200, Petr Baudis wrote:
> On Thu, May 10, 2007 at 09:48:05PM CEST, Carl Worth wrote:
>
> > The -n option is something I hadn't noticed, and that helps,
> > (except that what I've got to start with is a git revision name,
> > not a number).
>
> Hmm, yes, I've been thinking myself that it would be quite nice if I
> could just tell uncommit git revname right away.
It shouldn't be hard to do. Instead of uncommitting a fixed number of
commits, loop until you reach a specified commit.
> > But there are still some places where an experienced git user runs
> > into some awkward situations trying to use stg. For example, "stg
> > refresh" is basically always doing the equivalent of "commit -a"
> > so there's annoyingly no way to refresh only some of the modified
> > state into the commit.
>
> Yes, I fear that StGIT hides the index in a similar way that Cogito
> does. It seems like user index usage is undergoing kind of
> renaissance these days in Git community (at least it seems to me
> this way, maybe it's always been this way), it would probably make
> sense to allow making use of index in StGIT as well.
I agree. It's bad UI for StGIT to behave different from git, given
that easy interoperation is a goal.
> > Also, if I want to edit a commit message while under the influence
> > of stg, how do I do that? If I do "git commit --amend" will I
> > seriously confuse stg, (I'm guessing I would, but I don't know).
>
> I have no idea, but there's stg refresh -e.
Yes, you would confuse it; the patch ref would still point to the old
commit object, but that would no longer be an ancestor of HEAD. StGIT
doesn't know how to recover from this, so you'd have to do it by hand,
which is annoying.
I'm working on making StGIT more robust against this kind of damage,
but I'm not quite done yet.
> And yes, it would be cool if stg new could guess patch name from the
> subject line in a similar manner that stg uncommit does.
Good idea. This would be embarrassingly easy to do.
But you can kind of do it today. Just commit with git (my favorite
here is the emacs modes) and "stg assimilate"!
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
^ permalink raw reply
* Re: Merging commits together into a super-commit
From: linux @ 2007-05-10 21:55 UTC (permalink / raw)
To: git, kernel-hacker
Er... why is everyone making this so complex?
git checkout trunk # Switch to "trunk"
git checkout branch . # Overwrite with "branch", but stay on "trunk"
git commit
Now branch is the same tree object as "branch", but without the history.
Of course, you could be even nastier and di a direct
git-commit-tree branch^{tree} -p HEAD < commit_message
But that's not really necessary.
Starting from the branch, using the high-level commands is a bit awkward,
but it's easy enough to:
git-update-ref HEAD trunk
git-commit
^ permalink raw reply
* Re: [RFC] Second parent for reverts
From: Martin Langhoff @ 2007-05-10 22:33 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Junio C Hamano, Daniel Barkalow, git
In-Reply-To: <alpine.LFD.0.98.0705100927340.3986@woody.linux-foundation.org>
On 5/11/07, Linus Torvalds <torvalds@linux-foundation.org> wrote:
> Designing your SCM around the notion
> that everybody will use a totally integrated system is a mistake! It's a
> *huge* mistake.
A huge mistake _everyone else_ makes. git is the only scm that works
transparently with everything else -- witness the myriad of
importers/exporters/gateways we have, all depending on the fact that
git tracks content, and does not get distracted with fancy metadata.
cheers
martin
^ permalink raw reply
* Re: [FAQ?] Rationale for git's way to manage the index
From: Petr Baudis @ 2007-05-10 22:51 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: Junio C Hamano, Linus Torvalds, Martin Langhoff, git
In-Reply-To: <20070510220649.GL3141@spearce.org>
On Fri, May 11, 2007 at 12:06:49AM CEST, Shawn O. Pearce wrote:
> Which is why I'm considering shelving support (of some kind) in
> git-gui... but I'm probably not going to take away the current
> index view, nor am I going to take away the current hunk selection.
>
> But I would like to make it easier for non-patching-editing gods
> (Linus) to pull hunks in from a shelf, test them, and commit them.
>
> Said shelf probably would be another branch, much as Linus' nicely
> documented workflow does...
FWIW, Cogito supports shelving of uncommitted changes when switching a
branch (so that they are not retained through the switch but restored
when you switch back to the original branch) by committing the local
changes to refs/shelves/HEADNAME.
--
Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Ever try. Ever fail. No matter. // Try again. Fail again. Fail better.
-- Samuel Beckett
^ permalink raw reply
* Re: [PATCH] user-manual: Use "git config --global" instead of editing ~/.gitconfig
From: Petr Baudis @ 2007-05-10 23:00 UTC (permalink / raw)
To: J. Bruce Fields; +Cc: Johan Herland, git
In-Reply-To: <20070510220253.GZ13719@fieldses.org>
On Fri, May 11, 2007 at 12:02:53AM CEST, J. Bruce Fields wrote:
> On Thu, May 10, 2007 at 11:53:31PM +0200, Johan Herland wrote:
> > Use git-config for setting global user.name and user.email rather than
> > telling the user to edit ~/.gitconfig directly. This brings
> > user-manual.txt in line with tutorial.txt.
>
> The inconsistency is intentional. We want users to know about
> git-config, because it's helpful when writing scripts, and because it
> has a useful manpage. But we also want them to know about the
> config-file syntax, since most of us find reading and editing a file
> more intuitive than running git-config. So we use a mixture of both.
However, in that case I think this is not the good point to show
~/.gitconfig. Your goal at that point should be to get the user able to
commit as simply as possible, and having to manually edit some config
file is unnecessary hassle when you can just use these two simple
commands; also, we use the same commands in tutorials, crash courses
etc. So I really think that consistency is better here. The more viable
strategy is to mention that git-config really just plays with simple
text files at some... later point. :-)
--
Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Ever try. Ever fail. No matter. // Try again. Fail again. Fail better.
-- Samuel Beckett
^ permalink raw reply
* Re: quick bare clones taking longer?
From: Junio C Hamano @ 2007-05-10 23:22 UTC (permalink / raw)
To: Dan Nicholson; +Cc: Junio C Hamano, git
In-Reply-To: <91705d080705101508y26eabb37oaf90aa4d9a7e239a@mail.gmail.com>
"Dan Nicholson" <dbn.lists@gmail.com> writes:
> On 5/10/07, Junio C Hamano <junkio@cox.net> wrote:
> ...
>> We reject something whose portability is in question by saying
>> "It's not _even in_ POSIX". We on the other hand try to refrain
>> from saying "POSIX says you are supposed to have it, so screw
>> people that are not fully POSIX".
>
> Yes, I suppose. At the same time, git already implicitly requires more
> than, say, a Bourne shell.
Yes, and the line is fuzzy and case by case. I am playing it
safe as we are in pre-release freeze, also I condider /bin/pwd
much more universally available than "cd -P".
^ permalink raw reply
* [PATCH 1/1] Document -S option to git-log.
From: Johan Herland @ 2007-05-11 0:11 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 833 bytes --]
The -S option to git-log is used early on in the user manual. This
indicates that it is probably one of the more used options to git-log,
and should therefore be part of the git-log manual page.
Signed-off-by: Johan Herland <johan@herland.net>
---
Documentation/git-log.txt | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 49bb539..a10ec54 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -51,6 +51,9 @@ include::pretty-formats.txt[]
a record about how the tip of a reference was changed.
See also gitlink:git-reflog[1].
+-S<string>::
+ Show commits where the difference contains the change in <string>.
+
<paths>...::
Show only commits that affect the specified paths.
--
1.5.0.7
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply related
* [ANNOUNCE] GIT 1.5.2-rc3
From: Junio C Hamano @ 2007-05-11 0:23 UTC (permalink / raw)
To: git; +Cc: linux-kernel
Upcoming 1.5.2 will have three large-ish new features that the
user community wished to have for quite some time. I usually do
not CC the kernel list for -rc releases, but this one will
hopefully be pretty much the same as what the final one would
look like, so here it is.
We may get around fixing the long standing git-apply corner case
HPA's rebase problem unveiled before v1.5.2, but we might defer
it post 1.5.2 (it is not a regression). We'll see.
----------------------------------------------------------------
GIT v1.5.2 Release Notes (draft)
========================
Updates since v1.5.1
--------------------
* Plumbing level subproject support.
You can include a subdirectory that has an independent git
repository in your index and tree objects as a
"subproject". This plumbing (i.e. "core") level subproject
support explicitly excludes recursive behaviour.
The "subproject" entries in the index and trees are
incompatible with older versions of git. Experimenting with
the plumbing level support is encouraged, but be warned that
unless everybody in your project updates to this release or
later, using this feature would make your project
inaccessible by people with older versions of git.
* Plumbing level gitattributes support.
The gitattributes mechanism allows you to add 'attributes' to
paths in your project, and affect the way certain git
operations work. Currently you can influence if a path is
considered a binary or text (the former would be treated by
'git diff' not to produce textual output; the latter can go
through the line endings conversion process in repositories
with core.autocrlf set), expand and unexpand '$ident$' keyword
with blob object name, specify a custom 3-way merge driver,
and specify a custom diff driver. You can also apply
arbitrary filter to contents on check-in/check-out codepath
but this feature is an extremely sharp-edged razor and needs
to be handled with caution (do not use it unless you
understand the earlier mailing list discussion on keyword
expansion).
* The packfile format now optionally suports 64-bit index.
This release supports the "version 2" format of the .idx
file. This is automatically enabled when a huge packfile
needs more than 32-bit to express offsets of objects in the
pack
* Comes with an updated git-gui 0.7.0
* Updated gitweb:
- can show combined diff for merges;
- uses font size of user's preference, not hardcoded in pixels;
* New commands and options.
- "git bisect start" can optionally take a single bad commit and
zero or more good commits on the command line.
- "git shortlog" can optionally be told to wrap its output.
- "subtree" merge strategy allows another project to be merged in as
your subdirectory.
- "git format-patch" learned a new --subject-prefix=<string>
option, to override the built-in "[PATCH]".
- "git add -u" is a quick way to do the first stage of "git
commit -a" (i.e. update the index to match the working
tree); it obviously does not make a commit.
- "git clean" honors a new configuration, "clean.requireforce". When
set to true, this makes "git clean" a no-op, preventing you
from losing files by typing "git clean" when you meant to
say "make clean". You can still say "git clean -f" to
override this.
- "git log" family of commands learned --date={local,relative,default}
option. --date=relative is synonym to the --relative-date.
--date=local gives the timestamp in local timezone.
* Updated behavior of existing commands.
- When $GIT_COMMITTER_EMAIL or $GIT_AUTHOR_EMAIL is not set
but $EMAIL is set, the latter is used as a substitute.
- "git diff --stat" shows size of preimage and postimage blobs
for binary contents. Earlier it only said "Bin".
- "git lost-found" shows stuff that are unreachable except
from reflogs.
- "git checkout branch^0" now detaches HEAD at the tip commit
on the named branch, instead of just switching to the
branch (use "git checkout branch" to switch to the branch,
as before).
- "git bisect next" can be used after giving only a bad commit
without giving a good one (this starts bisection half-way to
the root commit). We used to refuse to operate without a
good and a bad commit.
- "git push", when pushing into more than one repository, does
not stop at the first error.
- "git archive" does not insist you to give --format parameter
anymore; it defaults to "tar".
- "git cvsserver" can use backends other than sqlite.
- "gitview" (in contrib/ section) learned to better support
"git-annotate".
- "git diff $commit1:$path2 $commit2:$path2" can now report
mode changes between the two blobs.
- Local "git fetch" from a repository whose object store is
one of the alternates (e.g. fetching from the origin in a
repository created with "git clone -l -s") avoids
downloading objects unnecessary.
- "git blame" uses .mailmap to canonicalize the author name
just like "git shortlog" does.
- "git pack-objects" pays attention to pack.depth
configuration variable.
- "git cherry-pick" and "git revert" does not use .msg file in
the working tree to prepare commit message; instead it uses
$GIT_DIR/MERGE_MSG as other commands.
* Builds
- git-p4import has never been installed; now there is an
installation option to do so.
- gitk and git-gui can be configured out.
- Generated documentation pages automatically get version
information from GIT_VERSION
- Parallel build with "make -j" descending into subdirectory
was fixed.
* Performance Tweaks
- Optimized "git-rev-list --bisect" (hence "git-bisect").
- Optimized "git-add $path" in a large directory, most of
whose contents are ignored.
- Optimized "git-diff-tree" for reduced memory footprint.
- The recursive merge strategy updated a worktree file that
was changed identically in two branches, when one of them
renamed it. We do not do that when there is no rename, so
match that behaviour.
- The default pack depth has been increased to 50, as the
recent addition of delta_base_cache makes deeper delta chains
much less expensive to access.
Fixes since v1.5.1
------------------
All of the fixes in v1.5.1 maintenance series are included in
this release, unless otherwise noted.
* Bugfixes
- Switching branches with "git checkout" refused to work when
a path changes from a file to a directory between the
current branch and the new branch, in order not to lose
possible local changes in the directory that is being turned
into a file with the switch. We now allow such a branch
switch after making sure that there is no locally modified
file nor un-ignored file in the directory. This has not
been backported to 1.5.1.x series, as it is rather an
intrusive change.
- Merging branches that have a file in one and a directory in
another at the same path used to get quite confused. We
handle such a case a bit more carefully, even though that is
still left as a conflict for the user to sort out. This
will not be backported to 1.5.1.x series, as it is rather an
intrusive change.
- git-fetch had trouble with a remote with insanely large number
of refs.
- "git clean -d -X" now does not remove non-excluded directories.
* Documentation updates
* Performance Tweaks
----------------------------------------------------------------
Changes since v1.5.2-rc2 are as follows:
Alex Riesen (1):
Use GIT_OBJECT_DIR for temporary files of pack-objects
Amos Waterland (1):
wcwidth redeclaration
Frank Lichtenheld (1):
cvsserver: Add test cases for git-cvsserver
Gerrit Pape (1):
gitweb: choose appropriate view for file type if a= parameter missing
J. Bruce Fields (7):
user-manual: more discussion of detached heads, fix typos
user-manual: add section ID's
user-manual: clean up fast-forward and dangling-objects sections
user-manual: fix .gitconfig editing examples
user-manual: miscellaneous editing
user-manual: stop deprecating the manual
user-manual: fix clone and fetch typos
Jakub Narebski (6):
gitweb: Add parsing of raw combined diff format to parse_difftree_raw_line
gitweb: Add combined diff support to git_difftree_body
gitweb: Add combined diff support to git_patchset_body
gitweb: Make it possible to use pre-parsed info in git_difftree_body
gitweb: Show combined diff for merge commits in 'commitdiff' view
gitweb: Show combined diff for merge commits in 'commit' view
Jari Aalto (1):
SPECIFYING RANGES typo fix: it it => it is
Jeff King (1):
Documentation: don't reference non-existent 'git-cvsapplycommit'
Johannes Sixt (1):
git-gui: Call changes "Staged" and "Unstaged" in file list titles.
Junio C Hamano (10):
diff: release blobs after generating textual diff.
diff.c: do not use a separate "size cache".
diff -M: release the preimage candidate blobs after rename detection.
diff -S: release the image after looking for needle in it
GIT v1.5.1.4
Update documentation links to point at 1.5.1.4
t9400: skip cvsserver test if Perl SQLite interface is unavailable
git-clone: don't get fooled by $PWD
.mailmap: add some aliases
GIT v1.5.2-rc3
Matthieu Moy (2):
Document git add -u introduced earlier.
Added a reference to git-add in the documentation for git-update-index
Michael Hendricks (1):
Document 'git-log --decorate'
Michael Spang (3):
dir.c: Omit non-excluded directories with dir->show_ignored
t7300: Basic tests for git-clean
Fix minor documentation errors
Paul Mackerras (1):
gitk: Allow user to choose whether to see the diff, old file, or new file
Petr Baudis (2):
Git.pm: config_boolean() -> config_bool()
gitweb: Do not use absolute font sizes
Quy Tonthat (2):
Add howto files to rpm packages.
Added new git-gui library files to rpm spec
Richard P. Curnow (2):
Fix documentation of tag in git-fast-import.txt
Fix documentation of tag in git-fast-import.txt
Shawn O. Pearce (32):
git-gui: Correctly handle UTF-8 encoded commit messages
git-gui: Allow spaces in path to 'wish'
git-gui: Include the subject in the status bar after commit
git-gui: Warn users before making an octopus merge
git-gui: Correct line wrapping for too many branch message
git-gui: Cleanup common font handling for font_ui
git-gui: Use option database defaults to set the font
git-gui: Refactor to use our git proc more often
git-gui: Track our own embedded values and rebuild when they change
Properly handle '0' filenames in import-tars
git-gui: Refactor into multiple files to save my sanity
git-gui: Move console procs into their own namespace
git-gui: Allow vi keys to scroll the diff/blame regions
git-gui: Move merge support into a namespace
git-gui: Show all possible branches for merge
git-gui: Include commit id/subject in merge choices
git-gui: Use vi-like keys in merge dialog
Remove duplicate exports from Makefile
git-gui: Allow shift-{k,j} to select a range of branches to merge
git-gui: Define a simple class/method system
git-gui: Convert browser, console to "class" format
git-gui: Don't attempt to inline array reads in methods
git-gui: Convert blame to the "class" way of doing things
git-gui: Use prefix if blame is run in a subdirectory
git-gui: Smarter command line parsing for browser, blame
git-gui: Generate blame on uncommitted working tree file
git-gui: Cleanup minor nits in blame code
git-gui: Format author/committer times in ISO format
Use .git/MERGE_MSG in cherry-pick/revert
git-gui: Paperbag fix blame in subdirectory
git gui 0.7.0
Correct error message in revert/cherry-pick
Theodore Ts'o (2):
Add pack.depth option to git-pack-objects.
Increase pack.depth default to 50
^ permalink raw reply
* Git Wiki after engine update lost macros; special pages like RecentChanges do not work
From: Jakub Narebski @ 2007-05-11 1:04 UTC (permalink / raw)
To: Petr Baudis; +Cc: git
After wiki engine (MoinMoin) update at http://git.or.cz/gitwiki MoinMoin
macros like {{RecentChanges}} or {{SystemInfo}} (by the way, somehow
link to SystemInfo was lost on FrontPage). It looks like some
configuration related to using Wikipedia-like links syntax was lost:
* You can make links using [[linkname]] (or even [[target|label]]
* If you ever need to use macros here, use a {{macroname}} syntax.
The second part is lost.
By the way automatic table of contents is now in a box which is
unnecessary narrow; see e.g. http://git.or.cz/gitwiki/GitFaq
Could it be configured to something more resembling previous style?
--
Jakub Narebski
Poland
^ permalink raw reply
* Re: [FAQ?] Rationale for git's way to manage the index
From: Jakub Narebski @ 2007-05-11 1:28 UTC (permalink / raw)
To: git
In-Reply-To: <873b26klkj.wl%cworth@cworth.org>
Carl Worth wrote:
> This reminds me of a confusing semantic issue that came about with the
> "new" add. It can be quite natural to commit a single file in one step
> with:
>
> git commit some-file.c
>
> or to do that in two steps with:
>
> git add some-file.c
> git commit
>
> (which is particularly useful if one wants to add multiple files).
>
> I recently found myself wanting to do a similar thing with a directory
> path. I can commit a path with:
>
> git commit path/
>
> but I don't get anything at all like the same semantics if I do:
>
> git add path/
> git commit
>
> (since "git add" will recursively add all untracked files under path/).
>
> Now the "recursively add all files" behavior is older, and has been an
> essential part of git-add forever. But I found it to be not at all
> what I wanted in this case, (where I'm now trained to say "git add" to
> stage things into the index).
>
> I don't know of any good fix for the problem now. Maybe I'll just need to
> remember to break out that old "git update-index" for a situation like
> this, but that sure feels clunky.
In the new version of git I *think* you can use "git add -u path/"
'git-add' [-n] [-v] [-f] [--interactive | -i] [-u] [--] <file>...
-u::
Update all files that git already knows about. This is what
"git commit -a" does in preparation for making a commit.
(in v1.5.2-rc0, documented in v1.5.2-rc3).
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* [StGIT PATCH 2/5] Generate patch names of more uniform length
From: Karl Hasselström @ 2007-05-11 1:40 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, Petr Baudis
In-Reply-To: <20070511013400.13161.9160.stgit@yoghurt>
From: Karl Hasselström <kha@treskal.com>
Cut the generated patch name at 30 characters after getting rid of
unwanted characters, not before. This gives patch names of more
uniform length, since consecutive unwanted characters were replaced by
a single dash.
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
stgit/utils.py | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/stgit/utils.py b/stgit/utils.py
index 18198c0..3612a4b 100644
--- a/stgit/utils.py
+++ b/stgit/utils.py
@@ -175,13 +175,13 @@ def call_editor(filename):
def patch_name_from_msg(msg):
"""Return a string to be used as a patch name. This is generated
- from the first 30 characters of the top line of the string passed
- as argument."""
+ from the top line of the string passed as argument, and is at most
+ 30 characters long."""
if not msg:
return None
- subject_line = msg[:30].lstrip().split('\n', 1)[0].lower()
- return re.sub('[\W]+', '-', subject_line).strip('-')
+ subject_line = msg.split('\n', 1)[0].lstrip().lower()
+ return re.sub('[\W]+', '-', subject_line).strip('-')[:30]
def make_patch_name(msg, unacceptable, default_name = 'patch',
alternative = True):
^ permalink raw reply related
* [StGIT PATCH 5/5] Uncommit to a named commit
From: Karl Hasselström @ 2007-05-11 1:40 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, Petr Baudis
In-Reply-To: <20070511013400.13161.9160.stgit@yoghurt>
From: Karl Hasselström <kha@treskal.com>
Add a new flag to "stg uncommit": --to. This flag takes a committish
parameter, and uncommits everything up until that commit.
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
stgit/commands/uncommit.py | 49 +++++++++++++++++++++++++++++++-------------
t/t1300-uncommit.sh | 8 +++++++
2 files changed, 42 insertions(+), 15 deletions(-)
diff --git a/stgit/commands/uncommit.py b/stgit/commands/uncommit.py
index f86af57..de6a37c 100644
--- a/stgit/commands/uncommit.py
+++ b/stgit/commands/uncommit.py
@@ -25,7 +25,7 @@ from stgit.utils import *
from stgit import stack, git
help = 'turn regular GIT commits into StGIT patches'
-usage = """%prog [<patchname1> [<patchname2> ... ] | -n [<prefix>]]
+usage = """%prog [<patchnames>] | -n NUM [<prefix>]] | -t <committish>
Take one or more git commits at the base of the current stack and turn
them into StGIT patches. The new patches are created as applied patches
@@ -35,24 +35,34 @@ By default, the number of patches to uncommit is determined by the
number of patch names provided on the command line. First name is used
for the first patch to uncommit, i.e. for the newest patch.
-The --number option specifies the number of patches to uncommit. In
+The -n/--number option specifies the number of patches to uncommit. In
this case, at most one patch name may be specified. It is used as
-prefix to which the patch number is appended.
+prefix to which the patch number is appended. If no patch names are
+provided on the command line, StGIT automatically generates them based
+on the first line of the patch description.
-If no patch names are provided on the command line, StGIT
-automatically generates them based on the first line of the patch
-description.
+The -t/--to option specifies that all commits up to and including the
+given commit should be uncommitted.
Only commits with exactly one parent can be uncommitted; in other
words, you can't uncommit a merge."""
options = [make_option('-n', '--number', type = 'int',
- help = 'uncommit the specified number of commits')]
+ help = 'uncommit the specified number of commits'),
+ make_option('-t', '--to',
+ help = 'uncommit to the specified commit')]
def func(parser, options, args):
"""Uncommit a number of patches.
"""
- if options.number:
+ if options.to:
+ if options.number:
+ parser.error('cannot give both --to and --number')
+ if len(args) != 0:
+ parser.error('cannot specify patch name with --to')
+ patch_nr = patchnames = None
+ to_commit = git.rev_parse(options.to)
+ elif options.number:
if options.number <= 0:
parser.error('invalid value passed to --number')
@@ -77,9 +87,6 @@ def func(parser, options, args):
raise CmdException, \
'This branch is protected. Uncommit is not permitted'
- print 'Uncommitting %d patches...' % patch_nr,
- sys.stdout.flush()
-
def get_commit(commit_id):
commit = git.Commit(commit_id)
try:
@@ -91,11 +98,23 @@ def func(parser, options, args):
commits = []
next_commit = crt_series.get_base()
- for i in xrange(patch_nr):
- commit, commit_id, parent = get_commit(next_commit)
- commits.append((commit, commit_id, parent))
- next_commit = parent
+ if patch_nr:
+ print 'Uncommitting %d patches...' % patch_nr,
+ for i in xrange(patch_nr):
+ commit, commit_id, parent = get_commit(next_commit)
+ commits.append((commit, commit_id, parent))
+ next_commit = parent
+ else:
+ print 'Uncommitting to %s...' % to_commit
+ while True:
+ commit, commit_id, parent = get_commit(next_commit)
+ commits.append((commit, commit_id, parent))
+ if commit_id == to_commit:
+ break
+ next_commit = parent
+ patch_nr = len(commits)
+ sys.stdout.flush()
for (commit, commit_id, parent), patchname in \
zip(commits, patchnames or (None for i in xrange(len(commits)))):
author_name, author_email, author_date = \
diff --git a/t/t1300-uncommit.sh b/t/t1300-uncommit.sh
index 519234e..2e7ff21 100755
--- a/t/t1300-uncommit.sh
+++ b/t/t1300-uncommit.sh
@@ -70,4 +70,12 @@ test_expect_success \
[ "$(stg id foo-patch//top)" = "$(stg id bar-patch//bottom)" ] &&
stg commit
'
+
+test_expect_success \
+ 'Uncommit the patches with --to' '
+ stg uncommit --to HEAD^ &&
+ [ "$(stg id foo-patch//top)" = "$(stg id bar-patch//bottom)" ] &&
+ stg commit
+'
+
test_done
^ permalink raw reply related
* [StGIT PATCH 1/5] Make the "name" argument to "stg new" optional
From: Karl Hasselström @ 2007-05-11 1:40 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, Petr Baudis
In-Reply-To: <20070511013400.13161.9160.stgit@yoghurt>
From: Karl Hasselström <kha@treskal.com>
If no name is given, one is generated from the commit message. This
can be very handy.
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
Documentation/stg-new.txt | 5 +++--
stgit/commands/common.py | 25 -------------------------
stgit/commands/new.py | 15 +++++++++++----
stgit/commands/pick.py | 2 +-
stgit/commands/uncommit.py | 3 +--
stgit/stack.py | 17 +++++++++++------
stgit/utils.py | 27 ++++++++++++++++++++++++++-
t/t1003-new.sh | 29 +++++++++++++++++++++++++++++
8 files changed, 82 insertions(+), 41 deletions(-)
diff --git a/Documentation/stg-new.txt b/Documentation/stg-new.txt
index 009659a..fbf2f67 100644
--- a/Documentation/stg-new.txt
+++ b/Documentation/stg-new.txt
@@ -10,7 +10,7 @@ stg-new - stgdesc:new[]
SYNOPSIS
--------
[verse]
-'stg' new [OPTIONS] <name>
+'stg' new [OPTIONS] [name]
DESCRIPTION
-----------
@@ -22,7 +22,8 @@ tree are not included in the patch. A stglink:refresh[] command is
needed for this.
The given <name> must be unique in the stack, and may only contain
-alphanumeric characters, dashes and underscores.
+alphanumeric characters, dashes and underscores. If no name is given,
+one is generated from the first line of the commit message.
An editor will be launched to edit the commit message to be used for
the patch, unless the '--message' flag already specified one. The
diff --git a/stgit/commands/common.py b/stgit/commands/common.py
index 674d8c1..28026da 100644
--- a/stgit/commands/common.py
+++ b/stgit/commands/common.py
@@ -323,31 +323,6 @@ def address_or_alias(addr_str):
for addr in addr_str.split(',')]
return ', '.join([addr for addr in addr_list if addr])
-def patch_name_from_msg(msg):
- """Return a string to be used as a patch name. This is generated
- from the first 30 characters of the top line of the string passed
- as argument."""
- if not msg:
- return None
-
- subject_line = msg[:30].lstrip().split('\n', 1)[0].lower()
- return re.sub('[\W]+', '-', subject_line).strip('-')
-
-def make_patch_name(msg, unacceptable, default_name = 'patch',
- alternative = True):
- """Return a patch name generated from the given commit message,
- guaranteed to make unacceptable(name) be false. If the commit
- message is empty, base the name on default_name instead."""
- patchname = patch_name_from_msg(msg)
- if not patchname:
- patchname = default_name
- if alternative and unacceptable(patchname):
- suffix = 0
- while unacceptable('%s-%d' % (patchname, suffix)):
- suffix += 1
- patchname = '%s-%d' % (patchname, suffix)
- return patchname
-
def prepare_rebase(real_rebase, force=None):
if not force:
# Be sure we won't loose results of stg-(un)commit by error.
diff --git a/stgit/commands/new.py b/stgit/commands/new.py
index 2c1e94b..f192e34 100644
--- a/stgit/commands/new.py
+++ b/stgit/commands/new.py
@@ -25,7 +25,7 @@ from stgit import stack, git
help = 'create a new patch and make it the topmost one'
-usage = """%prog [options] <name>
+usage = """%prog [options] [name]
Create a new, empty patch and make it the topmost one. If the
'--message' option is not passed, an editor is invoked with the
@@ -33,7 +33,10 @@ Create a new, empty patch and make it the topmost one. If the
/usr/share/stgit/templates/patchdescr.tmpl file used a as template,
together with generated lines. By default, the local changes in the
working tree are not included in the patch. A 'refresh' command is
-needed for this."""
+needed for this.
+
+If no name is given for the new patch, one is generated from the first
+line of the commit message."""
options = [make_option('-m', '--message',
help = 'use MESSAGE as the patch description'),
@@ -57,7 +60,11 @@ options = [make_option('-m', '--message',
def func(parser, options, args):
"""Creates a new patch
"""
- if len(args) != 1:
+ if len(args) == 0:
+ name = None # autogenerate a name
+ elif len(args) == 1:
+ name = args[0]
+ else:
parser.error('incorrect number of arguments')
check_conflicts()
@@ -66,7 +73,7 @@ def func(parser, options, args):
if options.author:
options.authname, options.authemail = name_email(options.author)
- crt_series.new_patch(args[0], message = options.message,
+ crt_series.new_patch(name, message = options.message,
show_patch = options.showpatch,
author_name = options.authname,
author_email = options.authemail,
diff --git a/stgit/commands/pick.py b/stgit/commands/pick.py
index edd614d..75def2a 100644
--- a/stgit/commands/pick.py
+++ b/stgit/commands/pick.py
@@ -75,7 +75,7 @@ def func(parser, options, args):
elif len(patch_branch) == 2:
patch = patch_branch[0]
else:
- patch = make_patch_name(commit.get_log(), crt_series.patch_exists)
+ patch = None
if options.parent:
parent = git_id(options.parent)
diff --git a/stgit/commands/uncommit.py b/stgit/commands/uncommit.py
index 462846c..04c7e52 100644
--- a/stgit/commands/uncommit.py
+++ b/stgit/commands/uncommit.py
@@ -95,8 +95,7 @@ def func(parser, options, args):
if patchnames:
patchname = patchnames[n]
else:
- patchname = make_patch_name(commit.get_log(),
- crt_series.patch_exists)
+ patchname = None
crt_series.new_patch(patchname,
can_edit = False, before_existing = True,
diff --git a/stgit/stack.py b/stgit/stack.py
index 76704e8..d0008bc 100644
--- a/stgit/stack.py
+++ b/stgit/stack.py
@@ -777,20 +777,25 @@ class Series(StgitObject):
before_existing = False, refresh = True):
"""Creates a new patch
"""
- self.__patch_name_valid(name)
- if self.patch_applied(name) or self.patch_unapplied(name):
- raise StackException, 'Patch "%s" already exists' % name
+ if name != None:
+ self.__patch_name_valid(name)
+ if self.patch_applied(name) or self.patch_unapplied(name):
+ raise StackException, 'Patch "%s" already exists' % name
if not message and can_edit:
- descr = edit_file(self, None, \
- 'Please enter the description for patch "%s" ' \
- 'above.' % name, show_patch)
+ descr = edit_file(
+ self, None,
+ 'Please enter the description for the patch above.',
+ show_patch)
else:
descr = message
head = git.get_head()
+ if name == None:
+ name = make_patch_name(descr, self.patch_exists)
+
patch = Patch(name, self.__patch_dir, self.__refs_dir)
patch.create()
diff --git a/stgit/utils.py b/stgit/utils.py
index d04d077..18198c0 100644
--- a/stgit/utils.py
+++ b/stgit/utils.py
@@ -1,7 +1,7 @@
"""Common utility functions
"""
-import errno, os, os.path, sys
+import errno, os, os.path, re, sys
from stgit.config import config
__copyright__ = """
@@ -172,3 +172,28 @@ def call_editor(filename):
if err:
raise EditorException, 'editor failed, exit code: %d' % err
print 'done'
+
+def patch_name_from_msg(msg):
+ """Return a string to be used as a patch name. This is generated
+ from the first 30 characters of the top line of the string passed
+ as argument."""
+ if not msg:
+ return None
+
+ subject_line = msg[:30].lstrip().split('\n', 1)[0].lower()
+ return re.sub('[\W]+', '-', subject_line).strip('-')
+
+def make_patch_name(msg, unacceptable, default_name = 'patch',
+ alternative = True):
+ """Return a patch name generated from the given commit message,
+ guaranteed to make unacceptable(name) be false. If the commit
+ message is empty, base the name on default_name instead."""
+ patchname = patch_name_from_msg(msg)
+ if not patchname:
+ patchname = default_name
+ if alternative and unacceptable(patchname):
+ suffix = 0
+ while unacceptable('%s-%d' % (patchname, suffix)):
+ suffix += 1
+ patchname = '%s-%d' % (patchname, suffix)
+ return patchname
diff --git a/t/t1003-new.sh b/t/t1003-new.sh
new file mode 100755
index 0000000..0be5d9b
--- /dev/null
+++ b/t/t1003-new.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Karl Hasselström
+#
+
+test_description='Test the new command.
+
+'
+
+. ./test-lib.sh
+
+test_expect_success \
+ 'Initialize the StGIT repository' '
+ stg init
+'
+
+test_expect_success \
+ 'Create a named patch' '
+ stg new foo -m foobar &&
+ [ $(stg applied -c) -eq 1 ]
+'
+
+test_expect_success \
+ 'Create a patch without giving a name' '
+ stg new -m yo &&
+ [ $(stg applied -c) -eq 2 ]
+'
+
+test_done
^ permalink raw reply related
* [StGIT PATCH 4/5] If any uncommit would fail, don't uncommit anything
From: Karl Hasselström @ 2007-05-11 1:40 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, Petr Baudis
In-Reply-To: <20070511013400.13161.9160.stgit@yoghurt>
From: Karl Hasselström <kha@treskal.com>
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
stgit/commands/uncommit.py | 26 +++++++++++++++-----------
1 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/stgit/commands/uncommit.py b/stgit/commands/uncommit.py
index 04c7e52..f86af57 100644
--- a/stgit/commands/uncommit.py
+++ b/stgit/commands/uncommit.py
@@ -80,23 +80,26 @@ def func(parser, options, args):
print 'Uncommitting %d patches...' % patch_nr,
sys.stdout.flush()
- for n in xrange(0, patch_nr):
- # retrieve the commit (only commits with a single parent are allowed)
- commit_id = crt_series.get_base()
+ def get_commit(commit_id):
commit = git.Commit(commit_id)
try:
parent, = commit.get_parents()
except ValueError:
- raise CmdException, 'Commit %s does not have exactly one parent' \
- % commit_id
+ raise CmdException('Commit %s does not have exactly one parent'
+ % commit_id)
+ return (commit, commit_id, parent)
+
+ commits = []
+ next_commit = crt_series.get_base()
+ for i in xrange(patch_nr):
+ commit, commit_id, parent = get_commit(next_commit)
+ commits.append((commit, commit_id, parent))
+ next_commit = parent
+
+ for (commit, commit_id, parent), patchname in \
+ zip(commits, patchnames or (None for i in xrange(len(commits)))):
author_name, author_email, author_date = \
name_email_date(commit.get_author())
-
- if patchnames:
- patchname = patchnames[n]
- else:
- patchname = None
-
crt_series.new_patch(patchname,
can_edit = False, before_existing = True,
top = commit_id, bottom = parent,
@@ -105,4 +108,5 @@ def func(parser, options, args):
author_email = author_email,
author_date = author_date)
+
print 'done'
^ permalink raw reply related
* [StGIT PATCH 0/5] Some tweaks and enhancements
From: Karl Hasselström @ 2007-05-11 1:39 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, Petr Baudis
The first and last patches of this series implements the things Petr
asked for (automatic patch naming with "stg new", and uncommitting to
a specified committish). Number 2 and 3 are small cleanups; 4 is a
refactoring that's useful in its own right, but also makes it easier
to do 5.
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
^ permalink raw reply
* [StGIT PATCH 3/5] Remove an unnecessary parameter to make_patch_name
From: Karl Hasselström @ 2007-05-11 1:40 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, Petr Baudis
In-Reply-To: <20070511013400.13161.9160.stgit@yoghurt>
From: Karl Hasselström <kha@treskal.com>
The "alternative" parameter was a boolean that indicated whether we
were interested in testing if the first generated name was acceptable,
or if we would just always accept it. But that can be accomplished by
giving an "unacceptable" function that always returns False, so
there's no need for an additional parameter.
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
stgit/commands/imprt.py | 8 +++++---
stgit/utils.py | 5 ++---
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/stgit/commands/imprt.py b/stgit/commands/imprt.py
index 89af472..6fcdc62 100644
--- a/stgit/commands/imprt.py
+++ b/stgit/commands/imprt.py
@@ -242,9 +242,11 @@ def __create_patch(filename, message, author_name, author_email,
patch = __strip_patch_name(patch)
if not patch:
- patch = make_patch_name(message, crt_series.patch_exists,
- alternative = not (options.ignore
- or options.replace))
+ if options.ignore or options.replace:
+ unacceptable_name = lambda name: False
+ else:
+ unacceptable_name = crt_series.patch_exists
+ patch = make_patch_name(message, unacceptable_name)
else:
# fix possible invalid characters in the patch name
patch = re.sub('[^\w.]+', '-', patch).strip('-')
diff --git a/stgit/utils.py b/stgit/utils.py
index 3612a4b..fbfe748 100644
--- a/stgit/utils.py
+++ b/stgit/utils.py
@@ -183,15 +183,14 @@ def patch_name_from_msg(msg):
subject_line = msg.split('\n', 1)[0].lstrip().lower()
return re.sub('[\W]+', '-', subject_line).strip('-')[:30]
-def make_patch_name(msg, unacceptable, default_name = 'patch',
- alternative = True):
+def make_patch_name(msg, unacceptable, default_name = 'patch'):
"""Return a patch name generated from the given commit message,
guaranteed to make unacceptable(name) be false. If the commit
message is empty, base the name on default_name instead."""
patchname = patch_name_from_msg(msg)
if not patchname:
patchname = default_name
- if alternative and unacceptable(patchname):
+ if unacceptable(patchname):
suffix = 0
while unacceptable('%s-%d' % (patchname, suffix)):
suffix += 1
^ permalink raw reply related
* Build Failure: GIT-GUI-VARS
From: Brian Gernhardt @ 2007-05-11 1:51 UTC (permalink / raw)
To: Git Mailing List
"make all" fails with "NO_TCLTK=y" because gitk-wish depends on GIT-
GUI-VARS which is defined inside the ifndef block.
AFAICT, either gitk-wish should be moved inside a ifndef block or an
else should be added with a phony GIT-GUI-VARS. I don't know which
is preferred.
Actually, I can't tell why make is trying to build it in the first
place. :-/ gitk-wish is added to OTHER_PROGRAMS inside a NO_TCLTK
block. (Debian oldstable, GNU Make 3.80, git repo v1.5.2-rc3)
And, while I'm poking through here, there's a line labeled "Backward
compatibility -- to be removed after 1.0". Git IDs itself as
1.5.2.rc3. Isn't that after 1.0? :-)
~~ Brian
^ permalink raw reply
* Re: Build Failure: GIT-GUI-VARS
From: Junio C Hamano @ 2007-05-11 2:30 UTC (permalink / raw)
To: Brian Gernhardt; +Cc: Git Mailing List
In-Reply-To: <FF405582-7769-4A08-87A0-680F8CD165DC@silverinsanity.com>
Brian Gernhardt <benji@silverinsanity.com> writes:
> Actually, I can't tell why make is trying to build it in the first
> place. :-/ gitk-wish is added to OTHER_PROGRAMS inside a NO_TCLTK
> block.
I do not either, and obviously does not reproduce for me. Time
for you to try "make -d" perhaps?
^ permalink raw reply
* Re: [ANNOUNCE] GIT 1.5.2-rc3
From: Alexander Litvinov @ 2007-05-11 3:23 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7virb0gqdz.fsf@assigned-by-dhcp.cox.net>
Hello.
> * Plumbing level subproject support.
>
> You can include a subdirectory that has an independent git
> repository in your index and tree objects as a
> "subproject". This plumbing (i.e. "core") level subproject
> support explicitly excludes recursive behaviour.
>
> The "subproject" entries in the index and trees are
> incompatible with older versions of git. Experimenting with
> the plumbing level support is encouraged, but be warned that
> unless everybody in your project updates to this release or
> later, using this feature would make your project
> inaccessible by people with older versions of git.
Is there any help onhow to use subprojects ? I did not found anything at
Documentation/ directiory.
Thanks for help,
Alexander Litvinov.
^ permalink raw reply
* Re: [PATCH] user-manual: Use "git config --global" instead of editing ~/.gitconfig
From: J. Bruce Fields @ 2007-05-11 3:46 UTC (permalink / raw)
To: Petr Baudis; +Cc: Johan Herland, git
In-Reply-To: <20070510230045.GF4489@pasky.or.cz>
On Fri, May 11, 2007 at 01:00:45AM +0200, Petr Baudis wrote:
> However, in that case I think this is not the good point to show
> ~/.gitconfig. Your goal at that point should be to get the user able
> to commit as simply as possible,
Sure.
> and having to manually edit some config file is unnecessary hassle
> when you can just use these two simple commands;
I don't get it; why are the two commands "simple", and editing a file a
"hassle"? In terms of, say, time required, or number of keystrokes, I
suspect the two are about the same. And it seems to me that:
- As users of a tool designed mainly to track changes to text
files, git users are likely to be pretty proficient at editing
text files.
- People also need to be able to view the configuration and
change it. If they make a typo on the first try, they may
need to do this sooner rather than later. With a config file,
this is trivial. With git-config, you have to learn at least
one new thing (how to query values).
- The config file is easier to read than the git-config output.
- You're going to have to edit some text anyway to plug your
name in, so we can't make this a pure cut-n-paste from the
docs.
> also, we use the same commands in tutorials, crash courses etc. So I
> really think that consistency is better here. The more viable strategy
> is to mention that git-config really just plays with simple text files
> at some... later point. :-)
So while I'm not convinced of the value of consistency here, if we have
to have consistency, I'd rather standardize on config-file-editing.
--b.
^ permalink raw reply
* Re: Anyone running GIT on native Windows
From: Han-Wen Nienhuys @ 2007-05-11 4:00 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Marco Costalba, git
In-Reply-To: <46417351.6BBA9313@eudaptics.com>
Johannes Sixt escreveu:
> Han-Wen Nienhuys wrote:
>> I packaged Mingw GIT using NSIS some time ago; see
>>
>> http://lilypond.org/git/binaries/mingw/
>>
>> Due various personal reasons, I haven't been able to update this, but I
>> will package a new version soon. Please try it to see whether there are
>> any rough edges.
>
> I've tried this shortly after you released it. But it did not work as
> expected. The symtom was (IIRC) that a simple
>
> git init
>
> said that 'init' is not a git-command. I tried this from CMD, not rxvt.
I don't know; I've tested it with Wine under Linux only. Maybe it couldn't
find the git-init.exe binary, have you checked that c:/Program Files/Git/usr/bin/
was in the path?
> relocation (i.e. an arbitrary installation directory). Could you please
> package the latest version from the 'devel' branch?
>
> git://repo.or.cz/git/mingw.git
http://lilypond.org/git/binaries/mingw/git-1.5.1-1.mingw.exe
--
Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen
^ permalink raw reply
* Re: [ANNOUNCE] GIT 1.5.2-rc3
From: Junio C Hamano @ 2007-05-11 4:28 UTC (permalink / raw)
To: Alexander Litvinov; +Cc: git
In-Reply-To: <200705111023.37676.litvinov2004@gmail.com>
Alexander Litvinov <litvinov2004@gmail.com> writes:
>> * Plumbing level subproject support.
> ...
> Is there any help onhow to use subprojects ? I did not found anything at
> Documentation/ directiory.
Sorry, you are expecting too much.
At this point, plumbing level support is just enough to
futureproof and not yet ready for mere mortals who need recipe
to be spoon-fed. Documentation needs to be written as well as
Porcelains need to be put on top of it.
It is enough to futureproof in the sense that if you fetch from
a remote repository of a project that _uses_ subprojects in its
objects, your end will not barf by saying "oops, I do not know
about a tree that can contain commit objects".
You can already play with it, though. Try:
git init ;# in an empty directory
mkdir sub
cd sub
git init
echo I am sublevel project >READ.ME
git add READ.ME
git commit -a -m 'sublevel initial commit'
cd .. ;# back to toplevel
echo I am toplevel project >READ.ME
mkdir dir
echo hello >dir/world
git add .
git commit -a -m 'toplevel initial commit'
A subproject in git is nothing but a directory that is a regular
git repository by its own right, but "tied to" the containing
repository. In this example, 'sub' is such a subproject.
At this point, if you run "git ls-tree -r -t HEAD", you would get
something like this:
$ git ls-tree -r -t HEAD
100644 blob 20a51da49ae274e8e6449b11ffad38bcddfee9f9 READ.ME
040000 tree dbd05ee6f475f80f28fb3bd4f4be3cec91547add dir
100644 blob ce013625030ba8dba906f756967f9e9ca394464a dir/world
160000 commit e502e6978a792adbec7e5e7a76a29a6597bda314 sub
The object name for 'sub' is the commit object name at HEAD of
the subproject. Verify it with:
$ (cd sub && git-rev-parse HEAD)"
e502e6978a792adbec7e5e7a76a29a6597bda314
The mode bit 160000 is something new -- git versions prior to
1.5.2 would not understand it, and fetching from this repository
would fail with older tools. That is what futureproofing is
mostly about.
Now, let's have a bit of fun by going down to subproject and
advance its history.
cd sub
echo touch it >>READ.ME
git commit -a -m 'subproject second commit'
cd .. ;# back to toplevel
What does that change look like to the toplevel project?
$ git diff
diff --git a/sub b/sub
index e502e69..300e71f 160000
--- a/sub
+++ b/sub
@@ -1 +1 @@
-Subproject commit e502e6978a792adbec7e5e7a76a29a6597bda314
+Subproject commit 300e71f68d458cdc8ce571b1b720ad16be992be2
That's right. The current state of the toplevel project records
that subproject was at its initial commit, but now you advanced
its history and notices the difference. You could even make a
commit to record that the updated subproject state should go
with the toplevel.
echo updated subproject >>READ.ME
git commit -a -m 'updated'
I was going to list what still do not work, but this is pretty
much it. For example, you would expect this to check out
subproject in the right state:
mv sub sss ;# stash away somewhere
git checkout -f
This "git checkout" *recreates* sub/ directory, but it does not
(yet) run git-init in it, nor check out the named commit (you
can find it out with "git ls-files -s sub") there. However, you
could at this point do:
cd sub
git init
git pull ../sss
cd .. ;# back to toplevel
and running "git diff" at the toplevel realizes that nothing has
changed.
If you are interested, go back to the list archive and start
reading around April 13th - 15th. We had quite an active
weekend; two neat features (subproject and attributes)
materialized almost at the same time.
^ permalink raw reply
* [PATCH] apply: do not get confused by symlinks in the middle
From: Junio C Hamano @ 2007-05-11 4:36 UTC (permalink / raw)
To: Git Mailing List; +Cc: Alex Riesen, Linus Torvalds, H. Peter Anvin
In-Reply-To: <7vmz0dmb2u.fsf@assigned-by-dhcp.cox.net>
HPA noticed that git-rebase fails when changes involve symlinks
in the middle of the hierarchy. Consider:
* The tree state before the patch is applied has arch/x86_64/boot
as a symlink pointing at ../i386/boot/
* The patch tries to remove arch/x86_64/boot symlink, and
create bunch of files there: .gitignore, Makefile, etc.
git-apply tries to be careful while applying patches; it never
touches the working tree until it is convinced that the patch
would apply cleanly. One of the check it does is that when it
knows a path is going to be created by the patch, it runs
lstat() on the path to make sure it does not exist.
This leads to a false alarm. Because we do not touch the
working tree before all the check passes, when we try to make
sure that arch/x86_64/boot/.gitignore does not exist yet, we
haven't removed the arch/x86_64/boot symlink. The lstat() check
ends up seeing arch/i386/boot/.gitignore through the
yet-to-be-removed symlink, and says "Hey, you already have a
file there, but what you fed me is a patch to create a new
file. I am not going to clobber what you have in the working
tree."
We have similar checks to see a file we are going to modify does
exist and match the preimage of the diff, which is done by
directly opening and reading the file.
For a file we are going to delete, we make sure that it does
exist and matches what is going to be removed (a removal patch
records the full preimage, so we check what you have in your
working tree matches it in full -- otherwise we would risk
losing your local changes), which again is done by directly
opening and reading the file.
These checks need to be adjusted so that they are not fooled by
symlinks in the middle.
- To make sure something does not exist, first lstat(). If it
does not exist, it does not, so be happy. If it _does_, we
might be getting fooled by a symlink in the middle, so break
leading paths and see if there are symlinks involved. When
we are checking for a path a/b/c/d, if any of a, a/b, a/b/c
is a symlink, then a/b/c/d does _NOT_ exist, for the purpose
of our test.
This would fix this particular case you saw, and would not
add extra overhead in the usual case.
- To make sure something already exists, first lstat(). If it
does not exist, barf (up to this, we already do). Even if it
does seem to exist, we might be getting fooled by a symlink
in the middle, so make sure leading paths are not symlinks.
This would make the normal codepath much more expensive for
deep trees, which is a bit worrisome.
This patch implements the first side of the check "making sure
it does not exist". The latter "making sure it exists" check is
not done yet, so applying the patch in reverse would still
fail, but we have to start from somewhere.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
* This should help the particular rebase go beyond the 0058
patch. While developing the new t4122 test I noticed that
read-tree -m -u (aka git-checkout) seems to have a very
similar problem, but I haven't dug into that yet.
builtin-apply.c | 69 +++++++++++++++++++++++++++++++++-----
t/t4122-apply-symlink-inside.sh | 57 ++++++++++++++++++++++++++++++++
2 files changed, 117 insertions(+), 9 deletions(-)
create mode 100755 t/t4122-apply-symlink-inside.sh
diff --git a/builtin-apply.c b/builtin-apply.c
index f94d0db..38d20ef 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -2009,6 +2009,63 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
return 0;
}
+static int has_symlink_component(const char *new_name)
+{
+ char path[PATH_MAX];
+ const char *sp, *ep;
+ char *dp;
+
+ sp = new_name;
+ dp = path;
+
+ while (1) {
+ size_t len;
+ struct stat st;
+
+ ep = strchr(sp, '/');
+ if (!ep)
+ break;
+ len = ep - sp;
+ if (PATH_MAX <= dp + len - path + 2)
+ return 0; /* new name is longer than that??? */
+ memcpy(dp, sp, len);
+ dp[len] = 0;
+
+ if (lstat(path, &st))
+ return 0; /* why? we already lstat() new_name successfully. */
+ if (S_ISLNK(st.st_mode))
+ return 1;
+
+ dp[len++] = '/';
+ dp = dp + len;
+ sp = ep + 1;
+ }
+ return 0;
+}
+
+static int check_to_create_blob(const char *new_name, int ok_if_exists)
+{
+ struct stat nst;
+ if (!lstat(new_name, &nst)) {
+ if (S_ISDIR(nst.st_mode) || ok_if_exists)
+ return 0;
+ /*
+ * A leading component of new_name might be a symlink
+ * that is going to be removed with this patch, but
+ * still pointing at somewhere that has the path.
+ * In such a case, path "new_name" does not exist as
+ * far as git is concerned.
+ */
+ if (has_symlink_component(new_name))
+ return 0;
+
+ return error("%s: already exists in working directory", new_name);
+ }
+ else if ((errno != ENOENT) && (errno != ENOTDIR))
+ return error("%s: %s", new_name, strerror(errno));
+ return 0;
+}
+
static int check_patch(struct patch *patch, struct patch *prev_patch)
{
struct stat st;
@@ -2095,15 +2152,9 @@ static int check_patch(struct patch *patch, struct patch *prev_patch)
!ok_if_exists)
return error("%s: already exists in index", new_name);
if (!cached) {
- struct stat nst;
- if (!lstat(new_name, &nst)) {
- if (S_ISDIR(nst.st_mode) || ok_if_exists)
- ; /* ok */
- else
- return error("%s: already exists in working directory", new_name);
- }
- else if ((errno != ENOENT) && (errno != ENOTDIR))
- return error("%s: %s", new_name, strerror(errno));
+ int err = check_to_create_blob(new_name, ok_if_exists);
+ if (err)
+ return err;
}
if (!patch->new_mode) {
if (0 < patch->is_new)
diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh
new file mode 100755
index 0000000..37c9a9f
--- /dev/null
+++ b/t/t4122-apply-symlink-inside.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+test_description='apply to deeper directory without getting fooled with symlink'
+. ./test-lib.sh
+
+lecho () {
+ for l_
+ do
+ echo "$l_"
+ done
+}
+
+test_expect_success setup '
+
+ mkdir -p arch/i386/boot arch/x86_64 &&
+ lecho 1 2 3 4 5 >arch/i386/boot/Makefile &&
+ ln -s ../i386/boot arch/x86_64/boot &&
+ git add . &&
+ test_tick &&
+ git commit -m initial &&
+ git branch test &&
+
+ rm arch/x86_64/boot &&
+ mkdir arch/x86_64/boot &&
+ lecho 2 3 4 5 6 >arch/x86_64/boot/Makefile &&
+ git add . &&
+ test_tick &&
+ git commit -a -m second &&
+
+ git format-patch --binary -1 --stdout >test.patch
+
+'
+
+test_expect_success apply '
+
+ git checkout test &&
+ git reset --hard && #### checkout seems to be buggy
+ git diff --exit-code test &&
+ git diff --exit-code --cached test &&
+ git apply --index test.patch
+
+'
+
+test_expect_success 'check result' '
+
+ git diff --exit-code master &&
+ git diff --exit-code --cached master &&
+ test_tick &&
+ git commit -m replay &&
+ T1=$(git rev-parse "master^{tree}") &&
+ T2=$(git rev-parse "HEAD^{tree}") &&
+ test "z$T1" = "z$T2"
+
+'
+
+test_done
+
--
1.5.2.rc3.706.g498a
^ permalink raw reply related
* Re: [PATCH] user-manual: Use "git config --global" instead of editing ~/.gitconfig
From: Junio C Hamano @ 2007-05-11 4:48 UTC (permalink / raw)
To: J. Bruce Fields; +Cc: Petr Baudis, Johan Herland, git
In-Reply-To: <20070511034653.GB26896@fieldses.org>
"J. Bruce Fields" <bfields@fieldses.org> writes:
> So while I'm not convinced of the value of consistency here, if we have
> to have consistency, I'd rather standardize on config-file-editing.
I obviously agree with everything you said.
I do not think "consistency" should weigh too much in the
teaching and learning process, which is what a manual is about.
It is beneficial to make the readers aware, early in the
process, that there typically are more than one ways to do
things, one suitable for scripting and the other for interactive
use. In the introductory part of the user-manual, I think it is
a very good idea to give a bit of glimpse of what is going on
under the hood, and config file is probably the easiest thing to
give that warm feeling of something they can understand is going
on to the readers.
^ 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