summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/completion/git-completion.bash84
-rw-r--r--contrib/completion/git-completion.zsh2
-rw-r--r--contrib/completion/git-prompt.sh38
-rw-r--r--contrib/credential/wincred/git-credential-wincred.c25
-rw-r--r--contrib/diff-highlight/README41
-rwxr-xr-xcontrib/diff-highlight/diff-highlight71
-rw-r--r--contrib/hooks/multimail/README43
-rw-r--r--contrib/hooks/multimail/README.Git6
-rwxr-xr-xcontrib/subtree/git-subtree.sh15
-rw-r--r--contrib/subtree/git-subtree.txt196
-rwxr-xr-xcontrib/workdir/git-new-workdir53
11 files changed, 354 insertions, 220 deletions
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 2fece98c60..bfc74e9d57 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -16,9 +16,9 @@
#
# To use these routines:
#
-# 1) Copy this file to somewhere (e.g. ~/.git-completion.sh).
+# 1) Copy this file to somewhere (e.g. ~/.git-completion.bash).
# 2) Add the following line to your .bashrc/.zshrc:
-# source ~/.git-completion.sh
+# source ~/.git-completion.bash
# 3) Consider changing your PS1 to also show the current branch,
# see git-prompt.sh for details.
#
@@ -186,7 +186,7 @@ fi
__gitcompappend ()
{
- local i=${#COMPREPLY[@]}
+ local x i=${#COMPREPLY[@]}
for x in $1; do
if [[ "$x" == "$3"* ]]; then
COMPREPLY[i++]="$2$x$4"
@@ -411,12 +411,9 @@ __git_refs_remotes ()
__git_remotes ()
{
- local i IFS=$'\n' d="$(__gitdir)"
+ local d="$(__gitdir)"
test -d "$d/remotes" && ls -1 "$d/remotes"
- for i in $(git --git-dir="$d" config --get-regexp 'remote\..*\.url' 2>/dev/null); do
- i="${i#remote.}"
- echo "${i/.url*/}"
- done
+ git --git-dir="$d" remote
}
__git_list_merge_strategies ()
@@ -668,8 +665,8 @@ __git_list_porcelain_commands ()
checkout-index) : plumbing;;
commit-tree) : plumbing;;
count-objects) : infrequent;;
- credential-cache) : credentials helper;;
- credential-store) : credentials helper;;
+ credential) : credentials;;
+ credential-*) : credentials helper;;
cvsexportcommit) : export;;
cvsimport) : import;;
cvsserver) : daemon;;
@@ -738,35 +735,29 @@ __git_list_porcelain_commands ()
__git_porcelain_commands=
__git_compute_porcelain_commands ()
{
- __git_compute_all_commands
test -n "$__git_porcelain_commands" ||
__git_porcelain_commands=$(__git_list_porcelain_commands)
}
-__git_pretty_aliases ()
+# Lists all set config variables starting with the given section prefix,
+# with the prefix removed.
+__git_get_config_variables ()
{
- local i IFS=$'\n'
- for i in $(git --git-dir="$(__gitdir)" config --get-regexp "pretty\..*" 2>/dev/null); do
- case "$i" in
- pretty.*)
- i="${i#pretty.}"
- echo "${i/ */}"
- ;;
- esac
+ local section="$1" i IFS=$'\n'
+ for i in $(git --git-dir="$(__gitdir)" config --get-regexp "^$section\..*" 2>/dev/null); do
+ i="${i#$section.}"
+ echo "${i/ */}"
done
}
+__git_pretty_aliases ()
+{
+ __git_get_config_variables "pretty"
+}
+
__git_aliases ()
{
- local i IFS=$'\n'
- for i in $(git --git-dir="$(__gitdir)" config --get-regexp "alias\..*" 2>/dev/null); do
- case "$i" in
- alias.*)
- i="${i#alias.}"
- echo "${i/ */}"
- ;;
- esac
- done
+ __git_get_config_variables "alias"
}
# __git_aliased_command requires 1 argument
@@ -980,7 +971,7 @@ _git_branch ()
case "$cur" in
--set-upstream-to=*)
- __gitcomp "$(__git_refs)" "" "${cur##--set-upstream-to=}"
+ __gitcomp_nl "$(__git_refs)" "" "${cur##--set-upstream-to=}"
;;
--*)
__gitcomp "
@@ -1048,7 +1039,7 @@ _git_checkout ()
_git_cherry ()
{
- __gitcomp "$(__git_refs)"
+ __gitcomp_nl "$(__git_refs)"
}
_git_cherry_pick ()
@@ -1305,7 +1296,7 @@ _git_gitk ()
}
__git_match_ctag() {
- awk "/^${1////\\/}/ { print \$1 }" "$2"
+ awk "/^${1//\//\\/}/ { print \$1 }" "$2"
}
_git_grep ()
@@ -1425,7 +1416,7 @@ __git_log_gitk_options="
# Options that go well for log and shortlog (not gitk)
__git_log_shortlog_options="
--author= --committer= --grep=
- --all-match
+ --all-match --invert-grep
"
__git_log_pretty_formats="oneline short medium full fuller email raw format:"
@@ -1451,7 +1442,7 @@ _git_log ()
return
;;
--decorate=*)
- __gitcomp "long short" "" "${cur##--decorate=}"
+ __gitcomp "full short no" "" "${cur##--decorate=}"
return
;;
--*)
@@ -1693,6 +1684,7 @@ _git_rebase ()
--committer-date-is-author-date --ignore-date
--ignore-whitespace --whitespace=
--autosquash --fork-point --no-fork-point
+ --autostash
"
return
@@ -1875,6 +1867,10 @@ _git_config ()
__gitcomp "$__git_send_email_suppresscc_options"
return
;;
+ sendemail.transferencoding)
+ __gitcomp "7bit 8bit quoted-printable base64"
+ return
+ ;;
--get|--get-all|--unset|--unset-all)
__gitcomp_nl "$(__git_config_get_set_variables)"
return
@@ -2009,6 +2005,7 @@ _git_config ()
color.status.changed
color.status.header
color.status.nobranch
+ color.status.unmerged
color.status.untracked
color.status.updated
color.ui
@@ -2120,6 +2117,7 @@ _git_config ()
http.noEPSV
http.postBuffer
http.proxy
+ http.sslCipherList
http.sslCAInfo
http.sslCAPath
http.sslCert
@@ -2183,6 +2181,7 @@ _git_config ()
pull.octopus
pull.twohead
push.default
+ push.followTags
rebase.autosquash
rebase.stat
receive.autogc
@@ -2256,12 +2255,7 @@ _git_remote ()
__git_complete_remote_or_refspec
;;
update)
- local i c='' IFS=$'\n'
- for i in $(git --git-dir="$(__gitdir)" config --get-regexp "remotes\..*" 2>/dev/null); do
- i="${i#remotes.}"
- c="$c ${i/ */}"
- done
- __gitcomp "$c"
+ __gitcomp "$(__git_get_config_variables "remotes")"
;;
*)
;;
@@ -2548,6 +2542,16 @@ _git_tag ()
__gitcomp_nl "$(__git_refs)"
;;
esac
+
+ case "$cur" in
+ --*)
+ __gitcomp "
+ --list --delete --verify --annotate --message --file
+ --sign --cleanup --local-user --force --column --sort
+ --contains --points-at
+ "
+ ;;
+ esac
}
_git_whatchanged ()
diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh
index 9f6f0fa558..e25541308a 100644
--- a/contrib/completion/git-completion.zsh
+++ b/contrib/completion/git-completion.zsh
@@ -9,7 +9,7 @@
#
# If your script is somewhere else, you can configure it on your ~/.zshrc:
#
-# zstyle ':completion:*:*:git:*' script ~/.git-completion.sh
+# zstyle ':completion:*:*:git:*' script ~/.git-completion.zsh
#
# The recommended way to install this script is to copy to '~/.zsh/_git', and
# then add the following to your ~/.zshrc file:
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index c5473dc8db..f18aedc73b 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -84,6 +84,11 @@
# GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
# the colored output of "git status -sb" and are available only when
# using __git_ps1 for PROMPT_COMMAND or precmd.
+#
+# If you would like __git_ps1 to do nothing in the case when the current
+# directory is set up to be ignored by git, then set
+# GIT_PS1_HIDE_IF_PWD_IGNORED to a nonempty value. Override this on the
+# repository level by setting bash.hideIfPwdIgnored to "false".
# check whether printf supports -v
__git_printf_supports_v=
@@ -270,7 +275,7 @@ __git_ps1_colorize_gitstring ()
__git_eread ()
{
- f="$1"
+ local f="$1"
shift
test -r "$f" && read "$@" <"$f"
}
@@ -288,6 +293,8 @@ __git_eread ()
# In this mode you can request colored hints using GIT_PS1_SHOWCOLORHINTS=true
__git_ps1 ()
{
+ # preserve exit status
+ local exit=$?
local pcmode=no
local detached=no
local ps1pc_start='\u@\h:\w '
@@ -299,10 +306,14 @@ __git_ps1 ()
ps1pc_start="$1"
ps1pc_end="$2"
printf_format="${3:-$printf_format}"
+ # set PS1 to a plain prompt so that we can
+ # simply return early if the prompt should not
+ # be decorated
+ PS1="$ps1pc_start$ps1pc_end"
;;
0|1) printf_format="${1:-$printf_format}"
;;
- *) return
+ *) return $exit
;;
esac
@@ -350,11 +361,7 @@ __git_ps1 ()
rev_parse_exit_code="$?"
if [ -z "$repo_info" ]; then
- if [ $pcmode = yes ]; then
- #In PC mode PS1 always needs to be set
- PS1="$ps1pc_start$ps1pc_end"
- fi
- return
+ return $exit
fi
local short_sha
@@ -369,6 +376,14 @@ __git_ps1 ()
local inside_gitdir="${repo_info##*$'\n'}"
local g="${repo_info%$'\n'*}"
+ if [ "true" = "$inside_worktree" ] &&
+ [ -n "${GIT_PS1_HIDE_IF_PWD_IGNORED-}" ] &&
+ [ "$(git config --bool bash.hideIfPwdIgnored)" != "false" ] &&
+ git check-ignore -q .
+ then
+ return $exit
+ fi
+
local r=""
local b=""
local step=""
@@ -412,10 +427,7 @@ __git_ps1 ()
else
local head=""
if ! __git_eread "$g/HEAD" head; then
- if [ $pcmode = yes ]; then
- PS1="$ps1pc_start$ps1pc_end"
- fi
- return
+ return $exit
fi
# is it a symbolic ref?
b="${head#ref: }"
@@ -475,7 +487,7 @@ __git_ps1 ()
if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
[ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
- git ls-files --others --exclude-standard --error-unmatch -- '*' >/dev/null 2>/dev/null
+ git ls-files --others --exclude-standard --error-unmatch -- ':/*' >/dev/null 2>/dev/null
then
u="%${ZSH_VERSION+%}"
fi
@@ -511,4 +523,6 @@ __git_ps1 ()
else
printf -- "$printf_format" "$gitstring"
fi
+
+ return $exit
}
diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c
index a1d38f035b..006134043a 100644
--- a/contrib/credential/wincred/git-credential-wincred.c
+++ b/contrib/credential/wincred/git-credential-wincred.c
@@ -111,14 +111,23 @@ static void write_item(const char *what, LPCWSTR wbuf, int wlen)
* Match an (optional) expected string and a delimiter in the target string,
* consuming the matched text by updating the target pointer.
*/
-static int match_part(LPCWSTR *ptarget, LPCWSTR want, LPCWSTR delim)
+
+static LPCWSTR wcsstr_last(LPCWSTR str, LPCWSTR find)
+{
+ LPCWSTR res = NULL, pos;
+ for (pos = wcsstr(str, find); pos; pos = wcsstr(pos + 1, find))
+ res = pos;
+ return res;
+}
+
+static int match_part_with_last(LPCWSTR *ptarget, LPCWSTR want, LPCWSTR delim, int last)
{
LPCWSTR delim_pos, start = *ptarget;
int len;
/* find start of delimiter (or end-of-string if delim is empty) */
if (*delim)
- delim_pos = wcsstr(start, delim);
+ delim_pos = last ? wcsstr_last(start, delim) : wcsstr(start, delim);
else
delim_pos = start + wcslen(start);
@@ -138,6 +147,16 @@ static int match_part(LPCWSTR *ptarget, LPCWSTR want, LPCWSTR delim)
return !want || (!wcsncmp(want, start, len) && !want[len]);
}
+static int match_part(LPCWSTR *ptarget, LPCWSTR want, LPCWSTR delim)
+{
+ return match_part_with_last(ptarget, want, delim, 0);
+}
+
+static int match_part_last(LPCWSTR *ptarget, LPCWSTR want, LPCWSTR delim)
+{
+ return match_part_with_last(ptarget, want, delim, 1);
+}
+
static int match_cred(const CREDENTIALW *cred)
{
LPCWSTR target = cred->TargetName;
@@ -146,7 +165,7 @@ static int match_cred(const CREDENTIALW *cred)
return match_part(&target, L"git", L":") &&
match_part(&target, protocol, L"://") &&
- match_part(&target, wusername, L"@") &&
+ match_part_last(&target, wusername, L"@") &&
match_part(&target, host, L"/") &&
match_part(&target, path, L"");
}
diff --git a/contrib/diff-highlight/README b/contrib/diff-highlight/README
index 502e03b305..836b97a730 100644
--- a/contrib/diff-highlight/README
+++ b/contrib/diff-highlight/README
@@ -58,6 +58,47 @@ following in your git configuration:
diff = diff-highlight | less
---------------------------------------------
+
+Color Config
+------------
+
+You can configure the highlight colors and attributes using git's
+config. The colors for "old" and "new" lines can be specified
+independently. There are two "modes" of configuration:
+
+ 1. You can specify a "highlight" color and a matching "reset" color.
+ This will retain any existing colors in the diff, and apply the
+ "highlight" and "reset" colors before and after the highlighted
+ portion.
+
+ 2. You can specify a "normal" color and a "highlight" color. In this
+ case, existing colors are dropped from that line. The non-highlighted
+ bits of the line get the "normal" color, and the highlights get the
+ "highlight" color.
+
+If no "new" colors are specified, they default to the "old" colors. If
+no "old" colors are specified, the default is to reverse the foreground
+and background for highlighted portions.
+
+Examples:
+
+---------------------------------------------
+# Underline highlighted portions
+[color "diff-highlight"]
+oldHighlight = ul
+oldReset = noul
+---------------------------------------------
+
+---------------------------------------------
+# Varying background intensities
+[color "diff-highlight"]
+oldNormal = "black #f8cbcb"
+oldHighlight = "black #ffaaaa"
+newNormal = "black #cbeecb"
+newHighlight = "black #aaffaa"
+---------------------------------------------
+
+
Bugs
----
diff --git a/contrib/diff-highlight/diff-highlight b/contrib/diff-highlight/diff-highlight
index 69a652e7b2..ffefc31a98 100755
--- a/contrib/diff-highlight/diff-highlight
+++ b/contrib/diff-highlight/diff-highlight
@@ -1,12 +1,23 @@
#!/usr/bin/perl
+use 5.008;
use warnings FATAL => 'all';
use strict;
# Highlight by reversing foreground and background. You could do
# other things like bold or underline if you prefer.
-my $HIGHLIGHT = "\x1b[7m";
-my $UNHIGHLIGHT = "\x1b[27m";
+my @OLD_HIGHLIGHT = (
+ color_config('color.diff-highlight.oldnormal'),
+ color_config('color.diff-highlight.oldhighlight', "\x1b[7m"),
+ color_config('color.diff-highlight.oldreset', "\x1b[27m")
+);
+my @NEW_HIGHLIGHT = (
+ color_config('color.diff-highlight.newnormal', $OLD_HIGHLIGHT[0]),
+ color_config('color.diff-highlight.newhighlight', $OLD_HIGHLIGHT[1]),
+ color_config('color.diff-highlight.newreset', $OLD_HIGHLIGHT[2])
+);
+
+my $RESET = "\x1b[m";
my $COLOR = qr/\x1b\[[0-9;]*m/;
my $BORING = qr/$COLOR|\s/;
@@ -57,6 +68,17 @@ show_hunk(\@removed, \@added);
exit 0;
+# Ideally we would feed the default as a human-readable color to
+# git-config as the fallback value. But diff-highlight does
+# not otherwise depend on git at all, and there are reports
+# of it being used in other settings. Let's handle our own
+# fallback, which means we will work even if git can't be run.
+sub color_config {
+ my ($key, $default) = @_;
+ my $s = `git config --get-color $key 2>/dev/null`;
+ return length($s) ? $s : $default;
+}
+
sub show_hunk {
my ($a, $b) = @_;
@@ -132,8 +154,8 @@ sub highlight_pair {
}
if (is_pair_interesting(\@a, $pa, $sa, \@b, $pb, $sb)) {
- return highlight_line(\@a, $pa, $sa),
- highlight_line(\@b, $pb, $sb);
+ return highlight_line(\@a, $pa, $sa, \@OLD_HIGHLIGHT),
+ highlight_line(\@b, $pb, $sb, \@NEW_HIGHLIGHT);
}
else {
return join('', @a),
@@ -143,20 +165,39 @@ sub highlight_pair {
sub split_line {
local $_ = shift;
- return map { /$COLOR/ ? $_ : (split //) }
- split /($COLOR*)/;
+ return utf8::decode($_) ?
+ map { utf8::encode($_); $_ }
+ map { /$COLOR/ ? $_ : (split //) }
+ split /($COLOR+)/ :
+ map { /$COLOR/ ? $_ : (split //) }
+ split /($COLOR+)/;
}
sub highlight_line {
- my ($line, $prefix, $suffix) = @_;
-
- return join('',
- @{$line}[0..($prefix-1)],
- $HIGHLIGHT,
- @{$line}[$prefix..$suffix],
- $UNHIGHLIGHT,
- @{$line}[($suffix+1)..$#$line]
- );
+ my ($line, $prefix, $suffix, $theme) = @_;
+
+ my $start = join('', @{$line}[0..($prefix-1)]);
+ my $mid = join('', @{$line}[$prefix..$suffix]);
+ my $end = join('', @{$line}[($suffix+1)..$#$line]);
+
+ # If we have a "normal" color specified, then take over the whole line.
+ # Otherwise, we try to just manipulate the highlighted bits.
+ if (defined $theme->[0]) {
+ s/$COLOR//g for ($start, $mid, $end);
+ chomp $end;
+ return join('',
+ $theme->[0], $start, $RESET,
+ $theme->[1], $mid, $RESET,
+ $theme->[0], $end, $RESET,
+ "\n"
+ );
+ } else {
+ return join('',
+ $start,
+ $theme->[1], $mid, $theme->[2],
+ $end
+ );
+ }
}
# Pairs are interesting to highlight only if we are going to end up
diff --git a/contrib/hooks/multimail/README b/contrib/hooks/multimail/README
index 477d65fed3..6efa4ffe17 100644
--- a/contrib/hooks/multimail/README
+++ b/contrib/hooks/multimail/README
@@ -456,34 +456,35 @@ consider sharing them with the community!
Getting involved
----------------
-git-multimail is an open-source project, built by volunteers. We
-would welcome your help!
+git-multimail is an open-source project, built by volunteers. We would
+welcome your help!
-The current maintainer is Michael Haggerty <mhagger@alum.mit.edu>.
+The current maintainers are Michael Haggerty <mhagger@alum.mit.edu>
+and Matthieu Moy <matthieu.moy@grenoble-inp.fr>.
-General discussion of git-multimail takes place on the main Git
-mailing list,
+Please note that although a copy of git-multimail is distributed in
+the "contrib" section of the main Git project, development takes place
+in a separate git-multimail repository on GitHub:
- git@vger.kernel.org
+ https://github.com/git-multimail/git-multimail
-Please CC emails regarding git-multimail to me so that I don't
-overlook them.
+Whenever enough changes to git-multimail have accumulated, a new
+code-drop of git-multimail will be submitted for inclusion in the Git
+project.
-The git-multimail project itself is currently hosted on GitHub:
+We use the GitHub issue tracker to keep track of bugs and feature
+requests, and we use GitHub pull requests to exchange patches (though,
+if you prefer, you can send patches via the Git mailing list with CC
+to the maintainers). Please sign off your patches as per the Git
+project practice.
- https://github.com/mhagger/git-multimail
+General discussion of git-multimail can take place on the main Git
+mailing list,
-We use the GitHub issue tracker to keep track of bugs and feature
-requests, and GitHub pull requests to exchange patches (though, if you
-prefer, you can send patches via the Git mailing list with cc to me).
-Please sign off your patches as per the Git project practice.
-
-Please note that although a copy of git-multimail will probably be
-distributed in the "contrib" section of the main Git project,
-development takes place in the separate git-multimail repository on
-GitHub! (Whenever enough changes to git-multimail have accumulated, a
-new code-drop of git-multimail will be submitted for inclusion in the
-Git project.)
+ git@vger.kernel.org
+
+Please CC emails regarding git-multimail to the maintainers so that we
+don't overlook them.
Footnotes
diff --git a/contrib/hooks/multimail/README.Git b/contrib/hooks/multimail/README.Git
index 129b771410..ab3ece5221 100644
--- a/contrib/hooks/multimail/README.Git
+++ b/contrib/hooks/multimail/README.Git
@@ -3,13 +3,13 @@ section of the Git project as a convenience to Git users.
git-multimail is developed as an independent project at the following
website:
- https://github.com/mhagger/git-multimail
+ https://github.com/git-multimail/git-multimail
The version in this directory was obtained from the upstream project
-on 2014-04-07 and consists of the "git-multimail" subdirectory from
+on 2015-04-27 and consists of the "git-multimail" subdirectory from
revision
- 1b32653bafc4f902535b9fc1cd9cae911325b870
+ 8c3aaafa873bf10de8dddf1d202c449b3eff3b42 refs/tags/1.0.2
Please see the README file in this directory for information about how
to report bugs or contribute to git-multimail.
diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index fa1a5839af..07bd77c4c8 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -26,7 +26,7 @@ b,branch= create a new branch from the split subtree
ignore-joins ignore prior --rejoin commits
onto= try connecting new tree to an existing one
rejoin merge the new branch back into HEAD
- options for 'add', 'merge', 'pull' and 'push'
+ options for 'add', 'merge', and 'pull'
squash merge subtree changes as a single commit
"
eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)"
@@ -51,14 +51,21 @@ prefix=
debug()
{
if [ -n "$debug" ]; then
- echo "$@" >&2
+ printf "%s\n" "$*" >&2
fi
}
say()
{
if [ -z "$quiet" ]; then
- echo "$@" >&2
+ printf "%s\n" "$*" >&2
+ fi
+}
+
+progress()
+{
+ if [ -z "$quiet" ]; then
+ printf "%s\r" "$*" >&2
fi
}
@@ -599,7 +606,7 @@ cmd_split()
eval "$grl" |
while read rev parents; do
revcount=$(($revcount + 1))
- say -n "$revcount/$revmax ($createcount) "
+ progress "$revcount/$revmax ($createcount)"
debug "Processing commit: $rev"
exists=$(cache_get $rev)
if [ -n "$exists" ]; then
diff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt
index 8272100ff5..60d76cdddf 100644
--- a/contrib/subtree/git-subtree.txt
+++ b/contrib/subtree/git-subtree.txt
@@ -81,12 +81,11 @@ merge::
changes into the latest <commit>. With '--squash',
creates only one commit that contains all the changes,
rather than merging in the entire history.
-
- If you use '--squash', the merge direction doesn't
- always have to be forward; you can use this command to
- go back in time from v2.5 to v2.4, for example. If your
- merge introduces a conflict, you can resolve it in the
- usual ways.
++
+If you use '--squash', the merge direction doesn't always have to be
+forward; you can use this command to go back in time from v2.5 to v2.4,
+for example. If your merge introduces a conflict, you can resolve it in
+the usual ways.
pull::
Exactly like 'merge', but parallels 'git pull' in that
@@ -107,21 +106,19 @@ split::
contents of <prefix> at the root of the project instead
of in a subdirectory. Thus, the newly created history
is suitable for export as a separate git repository.
-
- After splitting successfully, a single commit id is
- printed to stdout. This corresponds to the HEAD of the
- newly created tree, which you can manipulate however you
- want.
-
- Repeated splits of exactly the same history are
- guaranteed to be identical (i.e. to produce the same
- commit ids). Because of this, if you add new commits
- and then re-split, the new commits will be attached as
- commits on top of the history you generated last time,
- so 'git merge' and friends will work as expected.
-
- Note that if you use '--squash' when you merge, you
- should usually not just '--rejoin' when you split.
++
+After splitting successfully, a single commit id is printed to stdout.
+This corresponds to the HEAD of the newly created tree, which you can
+manipulate however you want.
++
+Repeated splits of exactly the same history are guaranteed to be
+identical (i.e. to produce the same commit ids). Because of this, if
+you add new commits and then re-split, the new commits will be attached
+as commits on top of the history you generated last time, so 'git merge'
+and friends will work as expected.
++
+Note that if you use '--squash' when you merge, you should usually not
+just '--rejoin' when you split.
OPTIONS
@@ -149,111 +146,98 @@ OPTIONS
OPTIONS FOR add, merge, push, pull
----------------------------------
--squash::
- This option is only valid for add, merge, push and pull
+ This option is only valid for add, merge, and pull
commands.
-
- Instead of merging the entire history from the subtree
- project, produce only a single commit that contains all
- the differences you want to merge, and then merge that
- new commit into your project.
-
- Using this option helps to reduce log clutter. People
- rarely want to see every change that happened between
- v1.0 and v1.1 of the library they're using, since none of the
- interim versions were ever included in their application.
-
- Using '--squash' also helps avoid problems when the same
- subproject is included multiple times in the same
- project, or is removed and then re-added. In such a
- case, it doesn't make sense to combine the histories
- anyway, since it's unclear which part of the history
- belongs to which subtree.
-
- Furthermore, with '--squash', you can switch back and
- forth between different versions of a subtree, rather
- than strictly forward. 'git subtree merge --squash'
- always adjusts the subtree to match the exactly
- specified commit, even if getting to that commit would
- require undoing some changes that were added earlier.
-
- Whether or not you use '--squash', changes made in your
- local repository remain intact and can be later split
- and send upstream to the subproject.
++
+Instead of merging the entire history from the subtree project, produce
+only a single commit that contains all the differences you want to
+merge, and then merge that new commit into your project.
++
+Using this option helps to reduce log clutter. People rarely want to see
+every change that happened between v1.0 and v1.1 of the library they're
+using, since none of the interim versions were ever included in their
+application.
++
+Using '--squash' also helps avoid problems when the same subproject is
+included multiple times in the same project, or is removed and then
+re-added. In such a case, it doesn't make sense to combine the
+histories anyway, since it's unclear which part of the history belongs
+to which subtree.
++
+Furthermore, with '--squash', you can switch back and forth between
+different versions of a subtree, rather than strictly forward. 'git
+subtree merge --squash' always adjusts the subtree to match the exactly
+specified commit, even if getting to that commit would require undoing
+some changes that were added earlier.
++
+Whether or not you use '--squash', changes made in your local repository
+remain intact and can be later split and send upstream to the
+subproject.
OPTIONS FOR split
-----------------
--annotate=<annotation>::
This option is only valid for the split command.
-
- When generating synthetic history, add <annotation> as a
- prefix to each commit message. Since we're creating new
- commits with the same commit message, but possibly
- different content, from the original commits, this can help
- to differentiate them and avoid confusion.
-
- Whenever you split, you need to use the same
- <annotation>, or else you don't have a guarantee that
- the new re-created history will be identical to the old
- one. That will prevent merging from working correctly.
- git subtree tries to make it work anyway, particularly
- if you use --rejoin, but it may not always be effective.
++
+When generating synthetic history, add <annotation> as a prefix to each
+commit message. Since we're creating new commits with the same commit
+message, but possibly different content, from the original commits, this
+can help to differentiate them and avoid confusion.
++
+Whenever you split, you need to use the same <annotation>, or else you
+don't have a guarantee that the new re-created history will be identical
+to the old one. That will prevent merging from working correctly. git
+subtree tries to make it work anyway, particularly if you use --rejoin,
+but it may not always be effective.
-b <branch>::
--branch=<branch>::
This option is only valid for the split command.
-
- After generating the synthetic history, create a new
- branch called <branch> that contains the new history.
- This is suitable for immediate pushing upstream.
- <branch> must not already exist.
++
+After generating the synthetic history, create a new branch called
+<branch> that contains the new history. This is suitable for immediate
+pushing upstream. <branch> must not already exist.
--ignore-joins::
This option is only valid for the split command.
-
- If you use '--rejoin', git subtree attempts to optimize
- its history reconstruction to generate only the new
- commits since the last '--rejoin'. '--ignore-join'
- disables this behaviour, forcing it to regenerate the
- entire history. In a large project, this can take a
- long time.
++
+If you use '--rejoin', git subtree attempts to optimize its history
+reconstruction to generate only the new commits since the last
+'--rejoin'. '--ignore-join' disables this behaviour, forcing it to
+regenerate the entire history. In a large project, this can take a long
+time.
--onto=<onto>::
This option is only valid for the split command.
-
- If your subtree was originally imported using something
- other than git subtree, its history may not match what
- git subtree is expecting. In that case, you can specify
- the commit id <onto> that corresponds to the first
- revision of the subproject's history that was imported
- into your project, and git subtree will attempt to build
- its history from there.
-
- If you used 'git subtree add', you should never need
- this option.
++
+If your subtree was originally imported using something other than git
+subtree, its history may not match what git subtree is expecting. In
+that case, you can specify the commit id <onto> that corresponds to the
+first revision of the subproject's history that was imported into your
+project, and git subtree will attempt to build its history from there.
++
+If you used 'git subtree add', you should never need this option.
--rejoin::
This option is only valid for the split command.
-
- After splitting, merge the newly created synthetic
- history back into your main project. That way, future
- splits can search only the part of history that has
- been added since the most recent --rejoin.
-
- If your split commits end up merged into the upstream
- subproject, and then you want to get the latest upstream
- version, this will allow git's merge algorithm to more
- intelligently avoid conflicts (since it knows these
- synthetic commits are already part of the upstream
- repository).
-
- Unfortunately, using this option results in 'git log'
- showing an extra copy of every new commit that was
- created (the original, and the synthetic one).
-
- If you do all your merges with '--squash', don't use
- '--rejoin' when you split, because you don't want the
- subproject's history to be part of your project anyway.
++
+After splitting, merge the newly created synthetic history back into
+your main project. That way, future splits can search only the part of
+history that has been added since the most recent --rejoin.
++
+If your split commits end up merged into the upstream subproject, and
+then you want to get the latest upstream version, this will allow git's
+merge algorithm to more intelligently avoid conflicts (since it knows
+these synthetic commits are already part of the upstream repository).
++
+Unfortunately, using this option results in 'git log' showing an extra
+copy of every new commit that was created (the original, and the
+synthetic one).
++
+If you do all your merges with '--squash', don't use '--rejoin' when you
+split, because you don't want the subproject's history to be part of
+your project anyway.
EXAMPLE 1. Add command
diff --git a/contrib/workdir/git-new-workdir b/contrib/workdir/git-new-workdir
index 75e8b25817..888c34a521 100755
--- a/contrib/workdir/git-new-workdir
+++ b/contrib/workdir/git-new-workdir
@@ -10,6 +10,10 @@ die () {
exit 128
}
+failed () {
+ die "unable to create new workdir '$new_workdir'!"
+}
+
if test $# -lt 2 || test $# -gt 3
then
usage "$0 <repository> <new_workdir> [<branch>]"
@@ -35,7 +39,7 @@ esac
# don't link to a configured bare repository
isbare=$(git --git-dir="$git_dir" config --bool --get core.bare)
-if test ztrue = z$isbare
+if test ztrue = "z$isbare"
then
die "\"$git_dir\" has core.bare set to true," \
" remove from \"$git_dir/config\" to use $0"
@@ -48,35 +52,54 @@ then
"a complete repository."
fi
-# don't recreate a workdir over an existing repository
-if test -e "$new_workdir"
+# make sure the links in the workdir have full paths to the original repo
+git_dir=$(cd "$git_dir" && pwd) || exit 1
+
+# don't recreate a workdir over an existing directory, unless it's empty
+if test -d "$new_workdir"
then
- die "destination directory '$new_workdir' already exists."
+ if test $(ls -a1 "$new_workdir/." | wc -l) -ne 2
+ then
+ die "destination directory '$new_workdir' is not empty."
+ fi
+ cleandir="$new_workdir/.git"
+else
+ cleandir="$new_workdir"
fi
-# make sure the links use full paths
-git_dir=$(cd "$git_dir"; pwd)
+mkdir -p "$new_workdir/.git" || failed
+cleandir=$(cd "$cleandir" && pwd) || failed
-# create the workdir
-mkdir -p "$new_workdir/.git" || die "unable to create \"$new_workdir\"!"
+cleanup () {
+ rm -rf "$cleandir"
+}
+siglist="0 1 2 15"
+trap cleanup $siglist
# create the links to the original repo. explicitly exclude index, HEAD and
# logs/HEAD from the list since they are purely related to the current working
# directory, and should not be shared.
for x in config refs logs/refs objects info hooks packed-refs remotes rr-cache svn
do
+ # create a containing directory if needed
case $x in
*/*)
- mkdir -p "$(dirname "$new_workdir/.git/$x")"
+ mkdir -p "$new_workdir/.git/${x%/*}"
;;
esac
- ln -s "$git_dir/$x" "$new_workdir/.git/$x"
+
+ ln -s "$git_dir/$x" "$new_workdir/.git/$x" || failed
done
-# now setup the workdir
-cd "$new_workdir"
+# commands below this are run in the context of the new workdir
+cd "$new_workdir" || failed
+
# copy the HEAD from the original repository as a default branch
-cp "$git_dir/HEAD" .git/HEAD
-# checkout the branch (either the same as HEAD from the original repository, or
-# the one that was asked for)
+cp "$git_dir/HEAD" .git/HEAD || failed
+
+# the workdir is set up. if the checkout fails, the user can fix it.
+trap - $siglist
+
+# checkout the branch (either the same as HEAD from the original repository,
+# or the one that was asked for)
git checkout -f $branch