Git development
 help / color / mirror / Atom feed
* Re: git-PS1 bash prompt setting
From: Sean @ 2006-11-27 12:56 UTC (permalink / raw)
  To: Shawn Pearce; +Cc: Johannes Schindelin, git, Theodore Tso
In-Reply-To: <20061127065400.GA19174@spearce.org>

On Mon, 27 Nov 2006 01:54:00 -0500
Shawn Pearce <spearce@spearce.org> wrote:

> I'm using something like this, and will be adding it to
> git-completion.bash tonight:
> 
> 	__git_ps1 ()
> 	{
> 		local b="$(git symbolic-ref HEAD 2>/dev/null)"
> 		if [ -n "$b" ]; then echo "(${b##refs/heads/})"; fi
> 	}
> 	PS1='[\u@\h \W$(__git_ps1)]\$ '
> 
> it works very well...

Yeah, when I first coded it I even looked at making it a bash loadable
to make it perform better but found the prototype to run acceptably,
so never bothered.   If Git does get a --show-ps1 option, people will
still be able to roll their own version to tweak the output format
as you did above.  Hopefully the standard format will work for most
though.


^ permalink raw reply

* Re: Some tips for doing a CVS importer
From: Markus Schiltknecht @ 2006-11-27 11:51 UTC (permalink / raw)
  To: Michael Haggerty; +Cc: Jon Smirl, Git Mailing List, dev, Shawn Pearce
In-Reply-To: <456ACAF3.1050608@alum.mit.edu>

Hi,

Michael Haggerty wrote:
> I am currently the main (and pretty much the only) cvs2svn maintainer.
> Development has been proceeding more slowly lately because (1) I'm very
> busy with my day job, and (2) nobody has stepped forward to help.

I understand very well. Same for me here with monotone's cvs_import vs. 
my day job... and then I also have a life ;-)

> Jon, I wish you wouldn't portray as obstinacy what is simply a lack of
> resources.  I would like very much to support other cvs2svn output
> formats.  I think it would be great if other projects could benefit from
> our work.  Most of the work I've been doing on cvs2svn lately has been
> towards supporting other output SCMs.

Really? Hm. I'm somehow sorry for not joining cvs2svn but running my own 
thing with monotone. But I really think it took me less time. OTOH, I'm 
far from finished, yet...

Anyway, I've made an attempt at solving the 'picking better sources for
symbols'-problem:

During parsing of all the *,v files, where I'm collecting events 
(commits, branching and tagging) into blobs, I do also remember 
'possible parent branches' for all the symbols (tag and branch events).

After that and *before* the blob sorting, I check all blobs and try to 
find one single parent branch for them. In the best case, those symbol 
blobs do have exactly one possible parent branch, then I just pick that 
one. If there are multiple possible parents, I try to pick the deepest. 
As branches are symbols themselves, I have to run that multiple times 
until all symbols are resolved.

An example: having branches ROOT -> A -> B -> C (branched in that order) 
plus a branch D derived from branch A.

The symbol blob for branch A: has only one possible parent: ROOT. Thus I 
assign A->parent_branch = ROOT.

Next comes the blob for branch C: it has two possible parents: branch B 
and branch A. At that point we know that A is derived from ROOT, but we 
don't have assigned a parent to B, yet. Thus we can not resolve C this time.

Then comes branch B: one parent: A. Mark it.

Next round, we process C again: this time, we know B is branched from A. 
Thus we can remove the possible parent A. Leaving only one possible 
parent branch: B.

Now, say we have a tag 'X', which ended up in a blob having A, B, C and 
D as possible parent branches. I currently remove A and B, as they are 
parents of C. But C and D still remain and conflict. I'm unable to 
resolve that symbol. I'm thinking about leaving such conflicts to the 
user to resolve.

I've not yet tested this algorithm extensively. Most larger repositories 
seem to fail somewhere, but not necessarily because of that symbol 
resolving algorithm... :-(

Any comments? Questions? Ideas? I hope to have explained clearly...

And I wish you all a lot of time for your open source projects and your 
families, friends, wifes, girl-friends, etc...! ;-)

Regards

Markus

^ permalink raw reply

* Re: Some tips for doing a CVS importer
From: Michael Haggerty @ 2006-11-27 11:29 UTC (permalink / raw)
  To: Marko Macek; +Cc: Jon Smirl, git
In-Reply-To: <4569BCB8.9030809@gmx.net>

Marko Macek wrote:
>> Another note for doing a converter. When combining things into change
>> sets, for git import the comments in the branches should not be mixed
>> between branches and the trunk when detecting change set. Git doesn't
>> allow simultaneous commits to the trunk and branches.
> 
> Yup, this is the current problem I'm facing now. Even for CVS->SVN
> conversion,
> I don't want to see multi-branch commits.

To avoid multi-branch commits, you have to start cvs2svn with an
--options file, and in the options file set

ctx.cross_project_commits = False


^ permalink raw reply

* Re: Some tips for doing a CVS importer
From: Michael Haggerty @ 2006-11-27 11:24 UTC (permalink / raw)
  To: Jon Smirl; +Cc: Git Mailing List, dev, Shawn Pearce
In-Reply-To: <9e4733910611201349s4d08b984g772c64982f148bfa@mail.gmail.com>

I am currently the main (and pretty much the only) cvs2svn maintainer.
Development has been proceeding more slowly lately because (1) I'm very
busy with my day job, and (2) nobody has stepped forward to help.

Jon Smirl wrote:
> #1) There needs to be a tool that can accurately import the
> repository. cvs2svn does not do this. The good programmers working on
> git could probably whip this out in a week or two if they wanted to.
> cvs2svn is very close but they refuse to solve the symbol dependency
> problem.

Jon, I wish you wouldn't portray as obstinacy what is simply a lack of
resources.  I would like very much to support other cvs2svn output
formats.  I think it would be great if other projects could benefit from
our work.  Most of the work I've been doing on cvs2svn lately has been
towards supporting other output SCMs.

Jon Smirl wrote:
> I gave up on my cvs2git code, cvs2svn has been refactored so badly
> that it was too much trouble tracking. It would be easier to write it
> again. Most of the smarts from the import process is in the
> git-fastimport code which Shawn has. cvs2svn underwent a major
> algorithm change after I wrote the first version of git2svn.

I hope that by "badly" you mean "extensively" and not "poorly" :-\  If
you mean "poorly", then I'd like to hear your feedback/suggestions.

A large amount of refactoring has been needed to make the change to
dependency-based conversion possible, and a lot more to help support
different output formats.  I understand that this causes difficulties
for people trying to do parallel development, but most of the
refactoring was done before your first appearance on the cvs2svn mailing
lists.  If you had let us know what you were working on, I would have
avoided making conflicting changes (as I did with Oswald Buddenhagen's
commit-dependencies changes).

Jon Smirl wrote:
> I have tried all of the available CVS importers. None of them are
> without problems. If anyone is interested in writing one for git here
> are some ideas on how to structure it.
> 
> 1) there is a working lex/yacc for CVS in the parsecvs source code
> 2) The first time you parse a CVS file record everything and don't
> parse it again.
> 3) When the file is first parsed use the deltas to generate the
> revisions and feed them to git-fastimport, just remember the SHA1 or
> an id in the import code. This is a critical step to getting decent
> performance.
> 4) If you do #1 and #2 you don't need to store CVS revision numbers
> and file names in memory. Because of that you can can easily do a
> Mozilla import in 2GB, probably 1GB.
> 5) When comparing CVS revisions only use the CVS timestamps as a last
> resort, instead use the dependency information in the CVS file
> 6) Match up commits by using an sha1 of the author and commit message
> 7) After all files are loaded, match up the symbols and insert them
> into the dependency chains, if any of the symbols depend on a branch
> commit the symbol lies on the branch, otherwise the symbol is on the
> trunk,
> 8) Do a topological sort to build the change set commit tree
> 9) when you hit a loop in the tree break up delta change sets until
> the loop can be removed, don't break up symbol change sets.
> 10) Mozilla has some large commits that were made over dial up. Commit
> change sets can span hours. All of these commits need to be merged
> into a single change set.
> 11) An algorithm needs to be developed for detecting branches merging
> back into the trunk
> 12) cvs2svn has excellent test cases, use them to test the new
> importer. The cvs2svn code is quite nice but it doesn't handle #7

Most of this is possible now using cvs2svn, but it is not enough.

But first there is a problem with your point #9.  It is in general not
possible to avoid breaking up symbol changesets, even if you are willing
to massacre the revision changesets.  CVS allows cases like this:

file1:

    1.1
    1.2 ----> branch "A"
              1.2.0.1
              1.2.0.2 ----> branch "B"

file2:

    1.1
    1.2 ----> branch "B"
              1.2.0.1
              1.2.0.2 ----> branch "A"

Clearly there is no way to create symbols "A" and "B" both in a single
changeset.

But even disallowing cases like the one above, it is often very
questionable whether you want to avoid breaking up symbol commits at all
costs.  For example, CVS allows


January:     file1<1.1>               file2<1.1>
February:    file1<1.1> tagged "T"
March:       file1<1.2>
November:                             file2<1.2>
December:                             file2<1.2> tagged "T"

In such a case, the only way to avoid splitting up the creation of tag
"T" would be to pretend that the commit file1<1.2> didn't occur in March
but rather in November.

The bottom line is that cvs2svn should do a better job of handling
symbols, but even then the git importer will necessarily have to deal
with some unusual CVS cases.

> Processing the symbols is integral to deciding how to build the change
> sets. Right now cvs2svn ignores the symbol dependency information and
> builds the change sets in a way that forces the mini-branches. That
> causes 60% of the 2,000 symbols in Mozilla CVS to end up as little
> branches. Look at the three commit example in the other thread to see
> exactly what the problem is.
>
> SVN hides the mini branch by creating a symbol like this:
>
> Symbol XXX, change set 70
> copy All from change set 50
> copy file A from change set 55
> copy file B,C from change set 60
> copy file D from change set 61
> copy file E,F,G from change set 63
> copy file H from change set 67
>
> It has to do all of those copies because the change sets weren't
> constructed while taking symbol dependency information into account.
>
> Symbol XXX can't copy from change set 69 because commits from after
> the symbol was created are included in change sets 51-69.

The vast majority of the mixed-source symbol creations have nothing to
do with honoring symbol dependencies, but rather with the fact the
cvs2svn is not so clever about deducing which branch should be used as
the source for a symbol (CVS often does not record this information
unambiguously).

Changes needed for git import:

The symbol dependency problem that Jon has focused on is IMO just the
least significant of three main changes that have to be made to support
git output from cvs2svn:

1. The symbol dependency problem.  Occasionally symbols are created in
an order that is inconsistent with the CVS dependency graph.  We want to
fix this in any case (even for SVN).  Work done so far: the symbol
dependency graph is already generated and recorded when the repository
is parsed, and the symbol dependencies are carried through the
conversion (though not yet used).

2. Symbols are often created using multiple branches as sources, when
they could be created from a single branch.  This happens because in
many cases CVS doesn't record unambiguously which branch was tagged, and
cvs2svn's heuristics are not especially clever.  A patch has been
submitted to fix this problem, but unfortunately it doesn't apply to
HEAD anymore.  See

http://cvs2svn.tigris.org/servlets/ReadMsg?list=dev&msgNo=1441

for a discussion.  (The main difficulty with picking better sources for
symbols is that the obvious approaches all require tons of intermediate
storage.)  I am currently trying to understand symbol handling in
cvs2svn well enough that I can port the patch to trunk.

3. The default current output format of cvs2svn is a single dump file
with file revisions in commit order.  For the distributed SCMs, it is
usually far more efficient to generate the file revisions file-by-file
(non-chronologically) during the initial parse of the CVS files, and
refer to the revisions by hash for the rest of the conversion.  In
October I added a bunch of hooks to cvs2svn to make this possible.  Work
remaining: code to reconstruct file text from CVS text + deltas,
including proper handling of line-end conventions and keyword
expansion/unexpansion, and of course the code to output the
reconstructed snapshots in a git-consumable format.

^ permalink raw reply

* Re: git-PS1 bash prompt setting
From: Nicolas Vilz @ 2006-11-27 10:50 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nicolas Vilz, git
In-Reply-To: <7vy7pxjmw7.fsf@assigned-by-dhcp.cox.net>

On Mon, Nov 27, 2006 at 12:48:24AM -0800, Junio C Hamano wrote:
> Nicolas Vilz <niv@iaglans.de> writes:
> 
> > I glued that in my system bashrc with the extension, that it shows to me
> > user.email out of repo-config, which is also very handy. So I am always
> > reminded to set my user.credentials in .git/config and i always know which 
> > role i play in the repository i am working at.
> 
> I think there is something wrong if the user needs to be
> _constantly_ reminded who he is.  Care to explain?

Yes, you are right. It sounds a bit strange. I try to setup a pool of 
configuration data for several linux-boxes which are kind of equal in a 
git repository.

Normally I just pull the config-branch from the repository to the
particular box, but sometimes i have to test the config and alter it...
and other people do as well. And therefore i like to be reminded
constantly who I am.

I glued that in the system bashrc, so I have it for services which
run as users and which configuration data has to be edited by the
services user... also here, several people are working on that machine
and make changes.

Sincerly

^ permalink raw reply

* Re: [PATCH 9/10] Allow completion of --committer and --author arguments to git log.
From: Nicolas Vilz @ 2006-11-27 10:28 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Junio C Hamano, git
In-Reply-To: <20061127084228.GI19745@spearce.org>

On Mon, Nov 27, 2006 at 03:42:28AM -0500, Shawn O. Pearce wrote:
> This is just a cute hack, but we can (easily) complete the parameter
> to --author or --committer in bash by asking for all possible authors
> or committers in this project from git log and offering them up as
> valid choices.
> 
> We replace spaces with dots as this prevents names with spaces from
> appearing as two parameters rather than one, yet it still matches the
> space in the field.
is it hard to train bash-completion to use "" and spaces instead of 
replacing spaces by dots? Besides, great feature, thank you for that... 
that's very handy.

Sincerly

^ permalink raw reply

* [PATCH 12/10] Teach bash about git-repo-config.
From: Shawn O. Pearce @ 2006-11-27  9:44 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

This is a really ugly completion script for git-repo-config, but it has
some nice properties.  I've added all of the documented configuration
parameters from Documentation/config.txt to the script, allowing the
user to complete any standard configuration parameter name.

We also have some intelligence for the remote.*.* and branch.*.* keys
by completing not only the key name (e.g. remote.origin) but also the
values (e.g. remote.*.fetch completes to the branches available on the
corresponding remote).

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 Yes, that's it.  I'm finally done tinkering with bash
 completion support for this week.  Total of 12 patches.
 Sorry about the numbering Junio; when I sent the first 10
 I thought I was going to bed, but then decided to stay
 up and hack a bit more...

 I know Linus would like to see the space thing corrected.
 I'll try to look at it next week if nobody beats me to it.

 contrib/completion/git-completion.bash |  154 ++++++++++++++++++++++++++++++++
 1 files changed, 154 insertions(+), 0 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 47b393d..a957165 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -43,6 +43,27 @@ __git_ps1 ()
 	fi
 }
 
+__git_heads ()
+{
+	local cmd i is_hash=y dir="${1:-$(__gitdir)}"
+	if [ -d "$dir" ]; then
+		for i in $(git --git-dir="$dir" \
+			for-each-ref --format='%(refname)' \
+			refs/heads ); do
+			echo "${i#refs/heads/}"
+		done
+		return
+	fi
+	for i in $(git-ls-remote "$dir" 2>/dev/null); do
+		case "$is_hash,$i" in
+		y,*) is_hash=n ;;
+		n,*^{}) is_hash=y ;;
+		n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
+		n,*) is_hash=y; echo "$i" ;;
+		esac
+	done
+}
+
 __git_refs ()
 {
 	local cmd i is_hash=y dir="${1:-$(__gitdir)}"
@@ -91,6 +112,23 @@ __git_refs2 ()
 	done
 }
 
+__git_refs_remotes ()
+{
+	local cmd i is_hash=y
+	for i in $(git-ls-remote "$1" 2>/dev/null); do
+		case "$is_hash,$i" in
+		n,refs/heads/*)
+			is_hash=y
+			echo "$i:refs/remotes/$1/${i#refs/heads/}"
+			;;
+		y,*) is_hash=n ;;
+		n,*^{}) is_hash=y ;;
+		n,refs/tags/*) is_hash=y;;
+		n,*) is_hash=y; ;;
+		esac
+	done
+}
+
 __git_remotes ()
 {
 	local i ngoff IFS=$'\n' d="$(__gitdir)"
@@ -520,6 +558,119 @@ _git_rebase ()
 	COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
 }
 
+_git_repo_config ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local prv="${COMP_WORDS[COMP_CWORD-1]}"
+	case "$prv" in
+	branch.*.remote)
+		COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
+		return
+		;;
+	branch.*.merge)
+		COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
+		return
+		;;
+	remote.*.fetch)
+		local remote="${prv#remote.}"
+		remote="${remote%.fetch}"
+		COMPREPLY=($(compgen -W "$(__git_refs_remotes "$remote")" \
+			-- "$cur"))
+		return
+		;;
+	remote.*.push)
+		local remote="${prv#remote.}"
+		remote="${remote%.push}"
+		COMPREPLY=($(compgen -W "$(git --git-dir="$(__gitdir)" \
+			for-each-ref --format='%(refname):%(refname)' \
+			refs/heads)" -- "$cur"))
+		return
+		;;
+	*.*)
+		COMPREPLY=()
+		return
+		;;
+	esac
+	case "$cur" in
+	--*)
+		COMPREPLY=($(compgen -W "
+			--global --list --replace-all
+			--get --get-all --get-regexp
+			--unset --unset-all
+			" -- "$cur"))
+		return
+		;;
+	branch.*.*)
+		local pfx="${cur%.*}."
+		cur="${cur##*.}"
+		COMPREPLY=($(compgen -P "$pfx" -W "remote merge" -- "$cur"))
+		return
+		;;
+	branch.*)
+		local pfx="${cur%.*}."
+		cur="${cur#*.}"
+		COMPREPLY=($(compgen -P "$pfx" -S . \
+			-W "$(__git_heads)" -- "$cur"))
+		return
+		;;
+	remote.*.*)
+		local pfx="${cur%.*}."
+		cur="${cur##*.}"
+		COMPREPLY=($(compgen -P "$pfx" -W "url fetch push" -- "$cur"))
+		return
+		;;
+	remote.*)
+		local pfx="${cur%.*}."
+		cur="${cur#*.}"
+		COMPREPLY=($(compgen -P "$pfx" -S . \
+			-W "$(__git_remotes)" -- "$cur"))
+		return
+		;;
+	esac
+	COMPREPLY=($(compgen -W "
+		apply.whitespace
+		core.fileMode
+		core.gitProxy
+		core.ignoreStat
+		core.preferSymlinkRefs
+		core.logAllRefUpdates
+		core.repositoryFormatVersion
+		core.sharedRepository
+		core.warnAmbiguousRefs
+		core.compression
+		core.legacyHeaders
+		i18n.commitEncoding
+		diff.color
+		diff.renameLimit
+		diff.renames
+		pager.color
+		status.color
+		log.showroot
+		show.difftree
+		showbranch.default
+		whatchanged.difftree
+		http.sslVerify
+		http.sslCert
+		http.sslKey
+		http.sslCAInfo
+		http.sslCAPath
+		http.maxRequests
+		http.lowSpeedLimit http.lowSpeedTime
+		http.noEPSV
+		pack.window
+		repack.useDeltaBaseOffset
+		pull.octopus pull.twohead
+		merge.summary
+		receive.unpackLimit
+		receive.denyNonFastForwards
+		user.name user.email
+		tar.umask
+		gitcvs.enabled
+		gitcvs.logfile
+		branch. remote.
+	" -- "$cur"))
+}
+
 _git_reset ()
 {
 	local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -572,6 +723,7 @@ _git ()
 	pull)        _git_pull ;;
 	push)        _git_push ;;
 	rebase)      _git_rebase ;;
+	repo-config) _git_repo_config ;;
 	reset)       _git_reset ;;
 	show)        _git_log ;;
 	show-branch) _git_log ;;
@@ -605,6 +757,7 @@ complete -o default            -F _git_name_rev git-name-rev
 complete -o default -o nospace -F _git_pull git-pull
 complete -o default -o nospace -F _git_push git-push
 complete -o default            -F _git_rebase git-rebase
+complete -o default            -F _git_repo_config git-repo-config
 complete -o default            -F _git_reset git-reset
 complete -o default            -F _git_log git-show
 complete -o default -o nospace -F _git_log git-show-branch
@@ -626,6 +779,7 @@ complete -o default -o nospace -F _git_ls_tree git-ls-tree.exe
 complete -o default            -F _git_merge_base git-merge-base.exe
 complete -o default            -F _git_name_rev git-name-rev.exe
 complete -o default -o nospace -F _git_push git-push.exe
+complete -o default            -F _git_repo_config git-repo-config
 complete -o default -o nospace -F _git_log git-show.exe
 complete -o default -o nospace -F _git_log git-show-branch.exe
 complete -o default -o nospace -F _git_log git-whatchanged.exe
-- 

^ permalink raw reply related

* Re: Idea for rebase strategy
From: Junio C Hamano @ 2006-11-27  9:26 UTC (permalink / raw)
  To: Andy Whitcroft; +Cc: Johannes Schindelin, git
In-Reply-To: <456AA9B2.8050409@shadowen.org>

Andy Whitcroft <apw@shadowen.org> writes:

>> 
>>        A---B---C---D---E topic
>>       /       /
>>   ---X---o---Y---Z master
>>                   \
>>                    A'--B'--C'--D' topic'
>
> Interestingly this trivial situation seems to works pretty much as is.
> A "git rebase --onto master X topic" (at least in my trivial test case)
> replayed A and B, squashed C as a noop, and copied D and E.  I did not
> need any information from the reflog.  Of course the reflog is a good
> way to find X as its first transaction but I did not need it to drive
> replay.

That is only because the pictures are showing the degenerated
case for simplicity, and the defect that the current rebase does
not even look at any merges is hidden by the fact that the merge
in the example C becomes no-op in the rebased history.  C could
be somewhere not between X and Z, in which case replaying the
merge becomes necessary.  Also when following from E to traverse
down the history of topic, at point C, you need to tell which of
B or Y are on the topic, and that's where you would rely on
ref-log.



^ permalink raw reply

* Re: Working copy as a pseudo-head
From: Junio C Hamano @ 2006-11-27  9:20 UTC (permalink / raw)
  To: Steven Grimm; +Cc: git
In-Reply-To: <456A9F93.1060801@midwinter.com>

Steven Grimm <koreth@midwinter.com> writes:

> Comments? Is this just nuts?

It is not "nuts", but we do not do it currently because it is a
bit too combersome to make it recoverable when things go wrong
while keeping the cost of making the necessary back-up for
recovery low.  When switching branches with local changes,
"git-checkout -m" needs to deal with a similar issue, but that
case only deal with two trees and a working tree.  To do this
for three-way merge, the conflicts you need to deal with become
more complex.

What needs to be done is very simple and straightforward.  You
first stash away the working tree state in a "virtual" tree,
then perform the usual 3-way merge using the common ancestor,
your HEAD and the other head, and come up with the merge result
without any of your changes.  Then you run another three-way
merge between the merge result and your previous working tree
state using the HEAD before the merge as the common ancestor.

       o---o---X (other head)
      /
  ---o---o---H (your head)
              \  
               W (your working tree)

==>

       o---o---X (other head)
      /         \
  ---o---o---H---M (merge between the base trees)
              \  
               W (your working tree)

==>

       o---o---X (other head)
      /         \
  ---o---o---H---M (merge between the base trees)
              \   \   
               W---W'(your working tree, updated for the merge result)

The design goal here is that you do not want to get any of your
local changes (i.e. "diff H W") to be included when you record
the result of the base merge 'M', and you would want the diff
between H and W to be forward-ported to the diff between M and
W'.

The first goal is already quite cumbersome when the merge
between X and H involve conflicing merges.  We use the working
tree to perform the file level merge (i.e. you edit them with
your favorite editor, and tell git when you are done), so while
that is happening we temporarily need to remove what was between
H and W.  If the merge is too complex and the user decides to
revert the whole thing, we would need to rewind the index and
working tree to the state at W (that means we would at least
need to stash the diff between H and index, and index and
working tree before starting the merge).

After the base merge is done, we would need to update the HEAD
to point at M.  Then we would perform the second three-way merge
between M and W using the original HEAD as their common
ancestor to come up with W'.  When this conflicts, there is no
easy way for the user to recover, other than going back to the
original state (that is, HEAD points at H and working tree is
W), even after having spent effort to merge between X and H to
produce M.

In common usage (call that "best current practice" if you may),
you do not have local changes in the working tree that would
conflict with the merge, so the current behaviour feels
cumbersome only when the safety valve kicks in.  After seeing it
fail due to the safety valve, you can do the same as what the
above pictures depict using existing tools.

 * preserve the local changes (i.e. come up with the virtual
   "W"):

	git commit -a -m WIP
	git tag -f WIP
        git reset --hard HEAD^

 * perform the merge in the now-clean tree:

	git pull ;# again from the same place
	edit edit
        test test
        git commit -a ;# resolve conflicts, test and commit

 * recover what you have preserved, and discard the virtual W:

	git pull --no-commit . WIP ;# merge in
	git reset ;# revert index to HEAD aka base merge result.
	git tag -d WIP

^ permalink raw reply

* Re: Idea for rebase strategy
From: Andy Whitcroft @ 2006-11-27  9:02 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Schindelin, git
In-Reply-To: <7vfyc5l24t.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
>> an idea hit me today: maybe we can make rebase work nicely with merges 
>> after all. We could record the original branch point and the new branch 
>> point for rebases.
> 
> One case that that would be simple enough, appear often enough
> in real life, and would be useful in practice is this:
> 
>        A---B---C---D---E topic
>       /       /
>   ---X---o---Y---Z master
> 
> After forking 'topic' at 'X' and built two commits A and B, the
> master has a related change in the area 'topic' works on, and a
> merge to adjust is made at C.  Then it builds two other commits
> D and E.  We should be able to rebase it on top of the master.
> 
> If we have a reliable ref-log for 'topic' that should be trivial
> to do.  It will be just the matter of replaying the log on top
> of master.  The ref-log says we committed two after we forked,
> so we replay them:
> 
>        A---B---C---D---E topic
>       /       /
>   ---X---o---Y---Z master
>                   \
>                    A'--B'
> 
> Then the log says we merged 'Y'.  We faithfully replay that,
> which wuold result in "fast-forward -- nothing special is
> needed" situation.  The remaining log entries would say we have
> two further commits, so replaying them would result in:
> 
>        A---B---C---D---E topic
>       /       /
>   ---X---o---Y---Z master
>                   \
>                    A'--B'--C'--D' topic'

Interestingly this trivial situation seems to works pretty much as is.
A "git rebase --onto master X topic" (at least in my trivial test case)
replayed A and B, squashed C as a noop, and copied D and E.  I did not
need any information from the reflog.  Of course the reflog is a good
way to find X as its first transaction but I did not need it to drive
replay.


^ permalink raw reply

* [PATCH 11/10] Corrected typo in format-patch bash completion.
From: Shawn O. Pearce @ 2006-11-27  8:54 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 This is in addition to the other 10 patches I just sent.
 It fixes the bad --in-reply-to option in patch 5/10.
 
 contrib/completion/git-completion.bash |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index df67f8e..47b393d 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -346,7 +346,7 @@ _git_format_patch ()
 			--numbered --start-number
 			--keep-subject
 			--signoff
-			--in-repy-to=
+			--in-reply-to=
 			--full-index --binary
 			" -- "$cur"))
 		return
-- 

^ permalink raw reply related

* Re: [PATCH 5/10] Teach bash how to complete git-format-patch.
From: Jakub Narebski @ 2006-11-27  8:50 UTC (permalink / raw)
  To: git
In-Reply-To: <20061127084143.GE19745@spearce.org>

Shawn O. Pearce wrote:

> +                       --in-repy-to=

--in-reply-to I think. And why his sole option has '='?
-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git


^ permalink raw reply

* Re: git-PS1 bash prompt setting
From: Junio C Hamano @ 2006-11-27  8:48 UTC (permalink / raw)
  To: Nicolas Vilz; +Cc: git
In-Reply-To: <20061126150523.GB18828@hermes.lan.home.vilz.de>

Nicolas Vilz <niv@iaglans.de> writes:

> I glued that in my system bashrc with the extension, that it shows to me
> user.email out of repo-config, which is also very handy. So I am always
> reminded to set my user.credentials in .git/config and i always know which 
> role i play in the repository i am working at.

I think there is something wrong if the user needs to be
_constantly_ reminded who he is.  Care to explain?

There was a talk on the list about making "git-commit" (and
"git-merge" that does not do a fast-forward) refuse to proceed
until user.nameemail are explicitly set in the configuration.  I
think that particular implementation is a bad idea because it
punishes people who have set up their GECOS and hostname sanely,
but at the same time I do understand that people who just
started to use git would be very unhappy to learn that their
names were misspelled in GECOS field only after accumulating a
couple dozen commits.


^ permalink raw reply

* [PATCH 10/10] Support bash completion of refs/remote.
From: Shawn O. Pearce @ 2006-11-27  8:42 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <de7beb117fb963e68e1085b773593be326ffd495.1164616814.git.spearce@spearce.org>

Now that people are really likely to start using separate remotes
(due to the default in git-clone changing) we should support ref
completion for these refs in as many commands as possible.

While we are working on this routine we should use for-each-ref
to obtain a list of local refs, as this should run faster than
peek-remote as it does not need to dereference tag objects in
order to produce the list of refs back to us.  It should also
be more friendly to users of StGIT as we won't generate a list
of the StGIT metadata refs.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 contrib/completion/git-completion.bash |   18 ++++++++++++++----
 1 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index b456a3b..df67f8e 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -47,16 +47,26 @@ __git_refs ()
 {
 	local cmd i is_hash=y dir="${1:-$(__gitdir)}"
 	if [ -d "$dir" ]; then
-		cmd=git-peek-remote
-	else
-		cmd=git-ls-remote
+		if [ -e "$dir/HEAD" ]; then echo HEAD; fi
+		for i in $(git --git-dir="$dir" \
+			for-each-ref --format='%(refname)' \
+			refs/tags refs/heads refs/remotes); do
+			case "$i" in
+				refs/tags/*)    echo "${i#refs/tags/}" ;;
+				refs/heads/*)   echo "${i#refs/heads/}" ;;
+				refs/remotes/*) echo "${i#refs/remotes/}" ;;
+				*)              echo "$i" ;;
+			esac
+		done
+		return
 	fi
-	for i in $($cmd "$dir" 2>/dev/null); do
+	for i in $(git-ls-remote "$dir" 2>/dev/null); do
 		case "$is_hash,$i" in
 		y,*) is_hash=n ;;
 		n,*^{}) is_hash=y ;;
 		n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;;
 		n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
+		n,refs/remotes/*) is_hash=y; echo "${i#refs/remotes/}" ;;
 		n,*) is_hash=y; echo "$i" ;;
 		esac
 	done
-- 

^ permalink raw reply related

* [PATCH 9/10] Allow completion of --committer and --author arguments to git log.
From: Shawn O. Pearce @ 2006-11-27  8:42 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <de7beb117fb963e68e1085b773593be326ffd495.1164616814.git.spearce@spearce.org>

This is just a cute hack, but we can (easily) complete the parameter
to --author or --committer in bash by asking for all possible authors
or committers in this project from git log and offering them up as
valid choices.

We replace spaces with dots as this prevents names with spaces from
appearing as two parameters rather than one, yet it still matches the
space in the field.

Currently my Mac OS X system takes ~5 seconds to compute the completions
for --author on git.git and ~4 seconds to compute the completions for
--committer on same.  I imagine it would take longer on more active
projects, but its a good way to see if the name you are entering is
going to be unique or not.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 contrib/completion/git-completion.bash |   20 ++++++++++++++++++++
 1 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 8acfb09..b456a3b 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -360,6 +360,26 @@ _git_log ()
 {
 	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
+	--committer=*)
+		COMPREPLY=($(compgen -W "$(git log --pretty=raw --all \
+			| sed -n -e "/^committer /{
+				s/^committer //
+				s/ <.*//
+				s/ /./g
+				p
+			}")" -- "${cur##--committer=}"))
+		return
+		;;
+	--author=*)
+		COMPREPLY=($(compgen -W "$(git log --pretty=raw --all \
+			| sed -n -e "/^author /{
+				s/^author //
+				s/ <.*//
+				s/ /./g
+				p
+			}")" -- "${cur##--author=}"))
+		return
+		;;
 	--pretty=*)
 		COMPREPLY=($(compgen -W "
 			oneline short medium full fuller email raw
-- 
1.4.4.1.ge3fb

^ permalink raw reply related

* [PATCH 8/10] Teach bash about git log/show/whatchanged options.
From: Shawn O. Pearce @ 2006-11-27  8:42 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <de7beb117fb963e68e1085b773593be326ffd495.1164616814.git.spearce@spearce.org>

Typing out options to git log/show/whatchanged can take a while, but
we can easily complete them with bash.  So list the most common ones,
especially --pretty=online|short|medium|... so that users don't need
to type everything out.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 contrib/completion/git-completion.bash |   34 ++++++++++++++++++++++++-------
 1 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index a61b6b9..8acfb09 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -358,6 +358,29 @@ _git_ls_tree ()
 
 _git_log ()
 {
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--pretty=*)
+		COMPREPLY=($(compgen -W "
+			oneline short medium full fuller email raw
+			" -- "${cur##--pretty=}"))
+		return
+		;;
+	--*)
+		COMPREPLY=($(compgen -W "
+			--max-count= --max-age= --since= --after=
+			--min-age= --before= --until=
+			--root --not --topo-order --date-order
+			--no-merges
+			--abbrev-commit --abbrev=
+			--relative-date
+			--author= --committer= --grep=
+			--all-match
+			--pretty= --name-status --name-only
+			" -- "$cur"))
+		return
+		;;
+	esac
 	__git_complete_revlist
 }
 
@@ -474,12 +497,6 @@ _git_reset ()
 	COMPREPLY=($(compgen -W "$opt $(__git_refs)" -- "$cur"))
 }
 
-_git_show ()
-{
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
-}
-
 _git ()
 {
 	local i c=1 command __git_dir
@@ -526,7 +543,7 @@ _git ()
 	push)        _git_push ;;
 	rebase)      _git_rebase ;;
 	reset)       _git_reset ;;
-	show)        _git_show ;;
+	show)        _git_log ;;
 	show-branch) _git_log ;;
 	whatchanged) _git_log ;;
 	*)           COMPREPLY=() ;;
@@ -559,7 +576,7 @@ complete -o default -o nospace -F _git_pull git-pull
 complete -o default -o nospace -F _git_push git-push
 complete -o default            -F _git_rebase git-rebase
 complete -o default            -F _git_reset git-reset
-complete -o default            -F _git_show git-show
+complete -o default            -F _git_log git-show
 complete -o default -o nospace -F _git_log git-show-branch
 complete -o default -o nospace -F _git_log git-whatchanged
 
@@ -579,6 +596,7 @@ complete -o default -o nospace -F _git_ls_tree git-ls-tree.exe
 complete -o default            -F _git_merge_base git-merge-base.exe
 complete -o default            -F _git_name_rev git-name-rev.exe
 complete -o default -o nospace -F _git_push git-push.exe
+complete -o default -o nospace -F _git_log git-show.exe
 complete -o default -o nospace -F _git_log git-show-branch.exe
 complete -o default -o nospace -F _git_log git-whatchanged.exe
 fi
-- 
1.4.4.1.ge3fb

^ permalink raw reply related

* [PATCH 7/10] Teach bash how to complete git-rebase.
From: Shawn O. Pearce @ 2006-11-27  8:42 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <de7beb117fb963e68e1085b773593be326ffd495.1164616814.git.spearce@spearce.org>

As git-rebase is a popular command bash should know how to complete
reference names and its long options.  We only support completions
which make sense given the current state of the repository, that
way users don't get shown --continue/--skip/--abort on the first
execution.

Also added support for long option --strategy to git-merge, as I
missed that option earlier and just noticed it while implementing
git-rebase.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 contrib/completion/git-completion.bash |   38 ++++++++++++++++++++++++++-----
 1 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 02a60a0..a61b6b9 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -367,16 +367,16 @@ _git_merge ()
 	case "$cur" in
 	--*)
 		COMPREPLY=($(compgen -W "
-			--no-commit --no-summary --squash
+			--no-commit --no-summary --squash --strategy
 			" -- "$cur"))
 		return
 	esac
-	if [ $COMP_CWORD -gt 1 -a X-s = "X${COMP_WORDS[COMP_CWORD-1]}" ]
-	then
+	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	-s|--strategy)
 		COMPREPLY=($(compgen -W "$(__git_merge_strategies)" -- "$cur"))
-	else
-		COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
-	fi
+		return
+	esac
+	COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
 }
 
 _git_merge_base ()
@@ -443,6 +443,30 @@ _git_push ()
 	esac
 }
 
+_git_rebase ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	if [ -d .dotest ]; then
+		COMPREPLY=($(compgen -W "
+			--continue --skip --abort
+			" -- "$cur"))
+		return
+	fi
+	case "$cur" in
+	--*)
+		COMPREPLY=($(compgen -W "
+			--onto --merge --strategy
+			" -- "$cur"))
+		return
+	esac
+	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	-s|--strategy)
+		COMPREPLY=($(compgen -W "$(__git_merge_strategies)" -- "$cur"))
+		return
+	esac
+	COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
+}
+
 _git_reset ()
 {
 	local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -500,6 +524,7 @@ _git ()
 	name-rev)    _git_name_rev ;;
 	pull)        _git_pull ;;
 	push)        _git_push ;;
+	rebase)      _git_rebase ;;
 	reset)       _git_reset ;;
 	show)        _git_show ;;
 	show-branch) _git_log ;;
@@ -532,6 +557,7 @@ complete -o default            -F _git_merge_base git-merge-base
 complete -o default            -F _git_name_rev git-name-rev
 complete -o default -o nospace -F _git_pull git-pull
 complete -o default -o nospace -F _git_push git-push
+complete -o default            -F _git_rebase git-rebase
 complete -o default            -F _git_reset git-reset
 complete -o default            -F _git_show git-show
 complete -o default -o nospace -F _git_log git-show-branch
-- 
1.4.4.1.ge3fb

^ permalink raw reply related

* [PATCH 6/10] Teach bash how to complete git-cherry-pick.
From: Shawn O. Pearce @ 2006-11-27  8:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <de7beb117fb963e68e1085b773593be326ffd495.1164616814.git.spearce@spearce.org>

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 contrib/completion/git-completion.bash |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 729e5a9..02a60a0 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -269,6 +269,21 @@ _git_checkout ()
 	COMPREPLY=($(compgen -W "-l -b $(__git_refs)" -- "$cur"))
 }
 
+_git_cherry_pick ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		COMPREPLY=($(compgen -W "
+			--edit --no-commit
+			" -- "$cur"))
+		;;
+	*)
+		COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
+		;;
+	esac
+}
+
 _git_diff ()
 {
 	__git_complete_file
@@ -472,6 +487,7 @@ _git ()
 	branch)      _git_branch ;;
 	cat-file)    _git_cat_file ;;
 	checkout)    _git_checkout ;;
+	cherry-pick) _git_cherry_pick ;;
 	diff)        _git_diff ;;
 	diff-tree)   _git_diff_tree ;;
 	fetch)       _git_fetch ;;
@@ -503,6 +519,7 @@ complete -o default            -F _gitk gitk
 complete -o default            -F _git_branch git-branch
 complete -o default -o nospace -F _git_cat_file git-cat-file
 complete -o default            -F _git_checkout git-checkout
+complete -o default            -F _git_cherry_pick git-cherry-pick
 complete -o default -o nospace -F _git_diff git-diff
 complete -o default            -F _git_diff_tree git-diff-tree
 complete -o default -o nospace -F _git_fetch git-fetch
-- 
1.4.4.1.ge3fb

^ permalink raw reply related

* [PATCH 5/10] Teach bash how to complete git-format-patch.
From: Shawn O. Pearce @ 2006-11-27  8:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <de7beb117fb963e68e1085b773593be326ffd495.1164616814.git.spearce@spearce.org>

Provide completion for currently known long options supported by
git-format-patch as well as the revision list specification argument,
which is generally either a refname or in the form a..b.

Since _git_log was the only code that knew how to complete a..b, but
we want to start adding option support to _git_log also refactor the
a..b completion logic out into its own function.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 contrib/completion/git-completion.bash |   60 +++++++++++++++++++++++--------
 1 files changed, 44 insertions(+), 16 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index a740d05..729e5a9 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -144,6 +144,26 @@ __git_complete_file ()
 	esac
 }
 
+__git_complete_revlist ()
+{
+	local pfx cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	*...*)
+		pfx="${cur%...*}..."
+		cur="${cur#*...}"
+		COMPREPLY=($(compgen -P "$pfx" -W "$(__git_refs)" -- "$cur"))
+		;;
+	*..*)
+		pfx="${cur%..*}.."
+		cur="${cur#*..}"
+		COMPREPLY=($(compgen -P "$pfx" -W "$(__git_refs)" -- "$cur"))
+		;;
+	*)
+		COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
+		;;
+	esac
+}
+
 __git_commands ()
 {
 	local i IFS=" "$'\n'
@@ -290,6 +310,26 @@ _git_fetch ()
 	esac
 }
 
+_git_format_patch ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		COMPREPLY=($(compgen -W "
+			--stdout --attach --thread
+			--output-directory
+			--numbered --start-number
+			--keep-subject
+			--signoff
+			--in-repy-to=
+			--full-index --binary
+			" -- "$cur"))
+		return
+		;;
+	esac
+	__git_complete_revlist
+}
+
 _git_ls_remote ()
 {
 	local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -303,22 +343,7 @@ _git_ls_tree ()
 
 _git_log ()
 {
-	local pfx cur="${COMP_WORDS[COMP_CWORD]}"
-	case "$cur" in
-	*...*)
-		pfx="${cur%...*}..."
-		cur="${cur#*...}"
-		COMPREPLY=($(compgen -P "$pfx" -W "$(__git_refs)" -- "$cur"))
-		;;
-	*..*)
-		pfx="${cur%..*}.."
-		cur="${cur#*..}"
-		COMPREPLY=($(compgen -P "$pfx" -W "$(__git_refs)" -- "$cur"))
-		;;
-	*)
-		COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
-		;;
-	esac
+	__git_complete_revlist
 }
 
 _git_merge ()
@@ -450,6 +475,7 @@ _git ()
 	diff)        _git_diff ;;
 	diff-tree)   _git_diff_tree ;;
 	fetch)       _git_fetch ;;
+	format-patch) _git_format_patch ;;
 	log)         _git_log ;;
 	ls-remote)   _git_ls_remote ;;
 	ls-tree)     _git_ls_tree ;;
@@ -480,6 +506,7 @@ complete -o default            -F _git_checkout git-checkout
 complete -o default -o nospace -F _git_diff git-diff
 complete -o default            -F _git_diff_tree git-diff-tree
 complete -o default -o nospace -F _git_fetch git-fetch
+complete -o default -o nospace -F _git_format_patch git-format-patch
 complete -o default -o nospace -F _git_log git-log
 complete -o default            -F _git_ls_remote git-ls-remote
 complete -o default -o nospace -F _git_ls_tree git-ls-tree
@@ -503,6 +530,7 @@ complete -o default            -F _git_branch git-branch.exe
 complete -o default -o nospace -F _git_cat_file git-cat-file.exe
 complete -o default -o nospace -F _git_diff git-diff.exe
 complete -o default -o nospace -F _git_diff_tree git-diff-tree.exe
+complete -o default -o nospace -F _git_format_patch git-format-patch.exe
 complete -o default -o nospace -F _git_log git-log.exe
 complete -o default -o nospace -F _git_ls_tree git-ls-tree.exe
 complete -o default            -F _git_merge_base git-merge-base.exe
-- 
1.4.4.1.ge3fb

^ permalink raw reply related

* [PATCH 4/10] Add current branch in PS1 support to git-completion.bash.
From: Shawn O. Pearce @ 2006-11-27  8:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <de7beb117fb963e68e1085b773593be326ffd495.1164616814.git.spearce@spearce.org>

Many users want to display the current branch name of the current git
repository as part of their PS1 prompt, much as their PS1 prompt might
also display the current working directory name.

We don't force our own PS1 onto the user.  Instead we let them craft
their own PS1 string and offer them the function __git_ps1 which they
can invoke to obtain either "" (when not in a git repository) or
"(%s)" where %s is the name of the current branch, as read from HEAD,
with the leading refs/heads/ removed.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 contrib/completion/git-completion.bash |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 1dfb592..a740d05 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -18,12 +18,31 @@
 #    2) Added the following line to your .bashrc:
 #        source ~/.git-completion.sh
 #
+#    3) Consider changing your PS1 to also show the current branch:
+#        PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
+#
+#       The argument to __git_ps1 will be displayed only if you
+#       are currently in a git repository.  The %s token will be
+#       the name of the current branch.
+#
 
 __gitdir ()
 {
 	echo "${__git_dir:-$(git rev-parse --git-dir 2>/dev/null)}"
 }
 
+__git_ps1 ()
+{
+	local b="$(git symbolic-ref HEAD 2>/dev/null)"
+	if [ -n "$b" ]; then
+		if [ -n "$1" ]; then
+			printf "$1" "${b##refs/heads/}"
+		else
+			printf " (%s)" "${b##refs/heads/}"
+		fi
+	fi
+}
+
 __git_refs ()
 {
 	local cmd i is_hash=y dir="${1:-$(__gitdir)}"
-- 
1.4.4.1.ge3fb

^ permalink raw reply related

* [PATCH 3/10] Teach bash how to complete options for git-name-rev.
From: Shawn O. Pearce @ 2006-11-27  8:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <de7beb117fb963e68e1085b773593be326ffd495.1164616814.git.spearce@spearce.org>

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 contrib/completion/git-completion.bash |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index b55431f..1dfb592 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -326,6 +326,12 @@ _git_merge_base ()
 	COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
 }
 
+_git_name_rev ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	COMPREPLY=($(compgen -W "--tags --all --stdin" -- "$cur"))
+}
+
 _git_pull ()
 {
 	local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -430,6 +436,7 @@ _git ()
 	ls-tree)     _git_ls_tree ;;
 	merge)       _git_merge;;
 	merge-base)  _git_merge_base ;;
+	name-rev)    _git_name_rev ;;
 	pull)        _git_pull ;;
 	push)        _git_push ;;
 	reset)       _git_reset ;;
@@ -459,6 +466,7 @@ complete -o default            -F _git_ls_remote git-ls-remote
 complete -o default -o nospace -F _git_ls_tree git-ls-tree
 complete -o default            -F _git_merge git-merge
 complete -o default            -F _git_merge_base git-merge-base
+complete -o default            -F _git_name_rev git-name-rev
 complete -o default -o nospace -F _git_pull git-pull
 complete -o default -o nospace -F _git_push git-push
 complete -o default            -F _git_reset git-reset
@@ -479,6 +487,7 @@ complete -o default -o nospace -F _git_diff_tree git-diff-tree.exe
 complete -o default -o nospace -F _git_log git-log.exe
 complete -o default -o nospace -F _git_ls_tree git-ls-tree.exe
 complete -o default            -F _git_merge_base git-merge-base.exe
+complete -o default            -F _git_name_rev git-name-rev.exe
 complete -o default -o nospace -F _git_push git-push.exe
 complete -o default -o nospace -F _git_log git-show-branch.exe
 complete -o default -o nospace -F _git_log git-whatchanged.exe
-- 
1.4.4.1.ge3fb

^ permalink raw reply related

* [PATCH 2/10] Hide plumbing/transport commands from bash completion.
From: Shawn O. Pearce @ 2006-11-27  8:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <de7beb117fb963e68e1085b773593be326ffd495.1164616814.git.spearce@spearce.org>

Users generally are not going to need to invoke plumbing-level commands
from within one line shell commands.  If they are invoking these commands
then it is likely that they are glueing them together into a shell script
to perform an action, in which case bash completion for these commands is
of relatively little use.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 contrib/completion/git-completion.bash |   62 +++++++++++++++++++++++++++++---
 1 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 28bd0e3..b55431f 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -125,6 +125,58 @@ __git_complete_file ()
 	esac
 }
 
+__git_commands ()
+{
+	local i IFS=" "$'\n'
+	for i in $(git help -a|egrep '^ ')
+	do
+		case $i in
+		check-ref-format) : plumbing;;
+		commit-tree)      : plumbing;;
+		convert-objects)  : plumbing;;
+		cvsserver)        : daemon;;
+		daemon)           : daemon;;
+		fetch-pack)       : plumbing;;
+		hash-object)      : plumbing;;
+		http-*)           : transport;;
+		index-pack)       : plumbing;;
+		local-fetch)      : plumbing;;
+		mailinfo)         : plumbing;;
+		mailsplit)        : plumbing;;
+		merge-*)          : plumbing;;
+		mktree)           : plumbing;;
+		mktag)            : plumbing;;
+		pack-objects)     : plumbing;;
+		pack-redundant)   : plumbing;;
+		pack-refs)        : plumbing;;
+		parse-remote)     : plumbing;;
+		patch-id)         : plumbing;;
+		peek-remote)      : plumbing;;
+		read-tree)        : plumbing;;
+		receive-pack)     : plumbing;;
+		rerere)           : plumbing;;
+		rev-list)         : plumbing;;
+		rev-parse)        : plumbing;;
+		runstatus)        : plumbing;;
+		sh-setup)         : internal;;
+		shell)            : daemon;;
+		send-pack)        : plumbing;;
+		show-index)       : plumbing;;
+		ssh-*)            : transport;;
+		stripspace)       : plumbing;;
+		symbolic-ref)     : plumbing;;
+		unpack-file)      : plumbing;;
+		unpack-objects)   : plumbing;;
+		update-ref)       : plumbing;;
+		update-server-info) : daemon;;
+		upload-archive)   : plumbing;;
+		upload-pack)      : plumbing;;
+		write-tree)       : plumbing;;
+		*) echo $i;;
+		esac
+	done
+}
+
 __git_aliases ()
 {
 	local i IFS=$'\n'
@@ -355,11 +407,11 @@ _git ()
 	done
 
 	if [ $c -eq $COMP_CWORD -a -z "$command" ]; then
-		COMPREPLY=($(compgen \
-			-W "--git-dir= --version \
-				$(git help -a|egrep '^ ') \
-			    $(__git_aliases)" \
-			-- "${COMP_WORDS[COMP_CWORD]}"))
+		COMPREPLY=($(compgen -W "
+			--git-dir= --version --exec-path
+			$(__git_commands)
+			$(__git_aliases)
+			" -- "${COMP_WORDS[COMP_CWORD]}"))
 		return;
 	fi
 
-- 
1.4.4.1.ge3fb

^ permalink raw reply related

* [PATCH 1/10] Teach git-completion.bash how to complete git-merge.
From: Shawn O. Pearce @ 2006-11-27  8:40 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Now that git-merge is high-level Porcelain users are going to expect
to be able to use it from the command line, in which case we really
should also be able to complete ref names as parameters.

I'm also including completion support for the merge strategies
that are supported by git-merge.sh, should the user wish to use a
different strategy than their default.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 contrib/completion/git-completion.bash |   30 ++++++++++++++++++++++++++++++
 1 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index a43a177..28bd0e3 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -81,6 +81,16 @@ __git_remotes ()
 	done
 }
 
+__git_merge_strategies ()
+{
+	sed -n "/^all_strategies='/{
+		s/^all_strategies='//
+		s/'//
+		p
+		q
+		}" "$(git --exec-path)/git-merge"
+}
+
 __git_complete_file ()
 {
 	local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}"
@@ -240,6 +250,24 @@ _git_log ()
 	esac
 }
 
+_git_merge ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		COMPREPLY=($(compgen -W "
+			--no-commit --no-summary --squash
+			" -- "$cur"))
+		return
+	esac
+	if [ $COMP_CWORD -gt 1 -a X-s = "X${COMP_WORDS[COMP_CWORD-1]}" ]
+	then
+		COMPREPLY=($(compgen -W "$(__git_merge_strategies)" -- "$cur"))
+	else
+		COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
+	fi
+}
+
 _git_merge_base ()
 {
 	local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -348,6 +376,7 @@ _git ()
 	log)         _git_log ;;
 	ls-remote)   _git_ls_remote ;;
 	ls-tree)     _git_ls_tree ;;
+	merge)       _git_merge;;
 	merge-base)  _git_merge_base ;;
 	pull)        _git_pull ;;
 	push)        _git_push ;;
@@ -376,6 +405,7 @@ complete -o default -o nospace -F _git_fetch git-fetch
 complete -o default -o nospace -F _git_log git-log
 complete -o default            -F _git_ls_remote git-ls-remote
 complete -o default -o nospace -F _git_ls_tree git-ls-tree
+complete -o default            -F _git_merge git-merge
 complete -o default            -F _git_merge_base git-merge-base
 complete -o default -o nospace -F _git_pull git-pull
 complete -o default -o nospace -F _git_push git-push
-- 
1.4.4.1.ge3fb

^ permalink raw reply related

* Re: Idea for rebase strategy
From: Junio C Hamano @ 2006-11-27  8:33 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0611270108160.30004@wbgn013.biozentrum.uni-wuerzburg.de>

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> an idea hit me today: maybe we can make rebase work nicely with merges 
> after all. We could record the original branch point and the new branch 
> point for rebases.

One case that that would be simple enough, appear often enough
in real life, and would be useful in practice is this:

       A---B---C---D---E topic
      /       /
  ---X---o---Y---Z master

After forking 'topic' at 'X' and built two commits A and B, the
master has a related change in the area 'topic' works on, and a
merge to adjust is made at C.  Then it builds two other commits
D and E.  We should be able to rebase it on top of the master.

If we have a reliable ref-log for 'topic' that should be trivial
to do.  It will be just the matter of replaying the log on top
of master.  The ref-log says we committed two after we forked,
so we replay them:

       A---B---C---D---E topic
      /       /
  ---X---o---Y---Z master
                  \
                   A'--B'

Then the log says we merged 'Y'.  We faithfully replay that,
which wuold result in "fast-forward -- nothing special is
needed" situation.  The remaining log entries would say we have
two further commits, so replaying them would result in:

       A---B---C---D---E topic
      /       /
  ---X---o---Y---Z master
                  \
                   A'--B'--C'--D' topic'


^ permalink raw reply

* Working copy as a pseudo-head
From: Steven Grimm @ 2006-11-27  8:19 UTC (permalink / raw)
  To: git

I was trying to explain to someone today why "git pull" fails if you 
have working-copy edits of one of the files that changed in the other 
branch, and it occurred to me that there may be a way to model the world 
so it doesn't fail. I am still relatively new to git so I hope this is 
not a totally idiotic idea.

Right now there is a hard distinction between what's in the working copy 
and the revision history of the tree. Merge is an operation on the 
revision history, and the working copy doesn't enter into it aside from 
the sanity check in git-merge to prevent you from inadvertently 
overwriting local edits.

What if instead, we had a notion of a temporary commit, call it WORK, 
that is ahead of what we currently think of as HEAD? That is, where now 
we have

A----B----C----D(HEAD)

we instead allowed

A----B----C----D(HEAD)----E(WORK)

When you do some operation that currently would complain about 
working-copy edits, it instead commits a WORK revision but does not 
adjust HEAD. Then it performs the operation against HEAD (advancing HEAD 
as needed) and rebases WORK under the newly merged HEAD, updating the 
working copy as a normal rebase would. Then, with one exception I'll get 
to below, it removes the WORK revision from the version history but 
leaves the contents of the working copy alone.

For example, say you have a pristine working copy of a branch with some 
history:

A----B----C(HEAD)

and you make some edits to the working copy. Now you want to pull down 
the latest changes from upstream, revision "X". So the system silently 
commits your work in progress to a temporary revision, which (while the 
merge is running) changes your history to:

A----B----C(HEAD)----D(WORK)

Then it merges the new changes with HEAD to form a new "Y" revision:

            /--D(WORK)
           /
A----B----C----Y(HEAD)
 \            /
  \-------X--/

Then it rebases WORK:

A----B----C----Y(HEAD)----D(WORK)
 \            /
  \-------X--/

And finally it removes WORK from the version history.

A----B----C----Y(HEAD) + working-copy edits
 \            /
  \-------X--/

I believe something like the above is currently how Cogito does its 
"update from the origin without losing working copy edits" thing, though 
it has to stash the working-copy edits in a temporary branch. Having the 
underlying functionality supported in the core git tools would be far 
preferable to having to hack around the lack of it in a frontend.

The one exception to the above flow is when you want to switch branches. 
Here, we create a WORK temporary commit on the current branch and move 
over to the new branch as normal, blowing away the WORK commit on the 
*new* branch, if any, and leaving its edits in the working copy. That 
allows you to freely switch back and forth between branches without 
worrying about whether you need to save your changes in progress, and 
without cluttering your repository with intermediate copies of files 
you're editing.

This is a behavior change! But I think the proposed behavior makes more 
sense. It treats the working copy as an extension of whatever branch 
you're on, rather than a separate entity that can flit back and forth 
between branches if there aren't conflicts or prevent you from changing 
branches at all if there are. It has always seemed confusing and 
inconsistent to me that, in some sense, doing a commit makes my changes 
LESS sticky -- that is,

echo foo >> testfile
git checkout other-branch
tail -1 testfile

says "foo", but

echo foo >> testfile
git commit -a
git checkout other-branch
tail -1 testfile

doesn't. I know (or I think I do) why it's doing that, but from a user 
experience point of view it's just weird, because it makes it look like 
"commit" reduces the importance of my change. And it also makes it a lot 
less convenient to pop over to another branch for a moment to check out 
the old version of some code I'm in the middle of rewriting.

Also, I realize I can use StGIT to get something like the above. But 
again, I think it'd be cleaner to support this in the underlying tool; 
"pull down some updates while I'm still working" is a very common usage 
model that's handled fine by other SCMs (Subversion, etc.) and right now 
with Git it requires a bunch of awkward extra commands. And preserving 
working-copy edits when switching branches seems like a huge convenience 
win to me; I have a hard time imagining how the current behavior is a 
time-saver for anyone (though I'm sure I'll hear all about it now!)

Comments? Is this just nuts?


^ permalink raw reply


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