diff options
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/completion/git-completion.bash | 84 | ||||
-rw-r--r-- | contrib/completion/git-completion.zsh | 2 | ||||
-rw-r--r-- | contrib/completion/git-prompt.sh | 38 | ||||
-rw-r--r-- | contrib/credential/wincred/git-credential-wincred.c | 25 | ||||
-rw-r--r-- | contrib/diff-highlight/README | 41 | ||||
-rwxr-xr-x | contrib/diff-highlight/diff-highlight | 71 | ||||
-rw-r--r-- | contrib/hooks/multimail/README | 43 | ||||
-rw-r--r-- | contrib/hooks/multimail/README.Git | 6 | ||||
-rwxr-xr-x | contrib/subtree/git-subtree.sh | 15 | ||||
-rw-r--r-- | contrib/subtree/git-subtree.txt | 196 | ||||
-rwxr-xr-x | contrib/workdir/git-new-workdir | 53 |
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 |