Windows NT DGPENSV2LPKMN 10.0 build 14393 (Windows Server 2016) AMD64
Apache/2.4.46 (Win64) OpenSSL/1.1.1h PHP/7.3.25
: 172.16.0.66 | : 172.16.0.254
Cant Read [ /etc/named.conf ]
7.3.25
SYSTEM
www.github.com/MadExploits
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
CPANEL RESET
CREATE WP USER
BLACK DEFEND!
README
+ Create Folder
+ Create File
[ A ]
[ C ]
[ D ]
C: /
laragon /
bin /
git /
mingw64 /
libexec /
git-core /
[ HOME SHELL ]
Name
Size
Permission
Action
mergetools
[ DIR ]
drwxrwxrwx
.mad-root
0
B
-rw-rw-rw-
Atlassian.Bitbucket.UI.Shared....
22.41
KB
-rw-rw-rw-
Atlassian.Bitbucket.dll
54.91
KB
-rw-rw-rw-
GitHub.UI.Shared.dll
29.41
KB
-rw-rw-rw-
GitHub.dll
83.91
KB
-rw-rw-rw-
GitLab.UI.Shared.dll
24.41
KB
-rw-rw-rw-
GitLab.dll
38.91
KB
-rw-rw-rw-
Microsoft.AzureRepos.dll
60.91
KB
-rw-rw-rw-
Microsoft.Identity.Client.Desk...
106.91
KB
-rw-rw-rw-
Microsoft.Identity.Client.Exte...
61.91
KB
-rw-rw-rw-
Microsoft.Identity.Client.dll
1.45
MB
-rw-rw-rw-
Microsoft.Web.WebView2.Core.dl...
217.91
KB
-rw-rw-rw-
Microsoft.Web.WebView2.WinForm...
32.91
KB
-rw-rw-rw-
Microsoft.Web.WebView2.Wpf.dll
36.91
KB
-rw-rw-rw-
Newtonsoft.Json.dll
685.91
KB
-rw-rw-rw-
System.Buffers.dll
21.41
KB
-rw-rw-rw-
System.CommandLine.dll
211.41
KB
-rw-rw-rw-
System.Memory.dll
138.91
KB
-rw-rw-rw-
System.Numerics.Vectors.dll
107.41
KB
-rw-rw-rw-
System.Runtime.CompilerService...
17.41
KB
-rw-rw-rw-
WebView2Loader.dll
108.92
KB
-rw-rw-rw-
edit.dll
53
KB
-rw-rw-rw-
gcmcore.dll
269.91
KB
-rw-rw-rw-
gcmcoreui.dll
23.41
KB
-rw-rw-rw-
gcmcoreuiwpf.dll
36.41
KB
-rw-rw-rw-
git-add--interactive
48.16
KB
-rw-rw-rw-
git-add.exe
44.55
KB
-rwxrwxrwx
git-am.exe
44.55
KB
-rwxrwxrwx
git-annotate.exe
44.55
KB
-rwxrwxrwx
git-apply.exe
44.55
KB
-rwxrwxrwx
git-archive.exe
44.55
KB
-rwxrwxrwx
git-bisect
2.09
KB
-rw-rw-rw-
git-bisect--helper.exe
44.55
KB
-rwxrwxrwx
git-blame.exe
44.55
KB
-rwxrwxrwx
git-branch.exe
44.55
KB
-rwxrwxrwx
git-bugreport.exe
44.55
KB
-rwxrwxrwx
git-bundle.exe
44.55
KB
-rwxrwxrwx
git-cat-file.exe
44.55
KB
-rwxrwxrwx
git-check-attr.exe
44.55
KB
-rwxrwxrwx
git-check-ignore.exe
44.55
KB
-rwxrwxrwx
git-check-mailmap.exe
44.55
KB
-rwxrwxrwx
git-check-ref-format.exe
44.55
KB
-rwxrwxrwx
git-checkout--worker.exe
44.55
KB
-rwxrwxrwx
git-checkout-index.exe
44.55
KB
-rwxrwxrwx
git-checkout.exe
44.55
KB
-rwxrwxrwx
git-cherry-pick.exe
44.55
KB
-rwxrwxrwx
git-cherry.exe
44.55
KB
-rwxrwxrwx
git-citool
687
B
-rw-rw-rw-
git-clean.exe
44.55
KB
-rwxrwxrwx
git-clone.exe
44.55
KB
-rwxrwxrwx
git-column.exe
44.55
KB
-rwxrwxrwx
git-commit-graph.exe
44.55
KB
-rwxrwxrwx
git-commit-tree.exe
44.55
KB
-rwxrwxrwx
git-commit.exe
44.55
KB
-rwxrwxrwx
git-config.exe
44.55
KB
-rwxrwxrwx
git-count-objects.exe
44.55
KB
-rwxrwxrwx
git-credential-cache--daemon.e...
44.55
KB
-rwxrwxrwx
git-credential-cache.exe
44.55
KB
-rwxrwxrwx
git-credential-store.exe
44.55
KB
-rwxrwxrwx
git-credential-wincred.exe
57.08
KB
-rwxrwxrwx
git-credential.exe
44.55
KB
-rwxrwxrwx
git-daemon.exe
2.05
MB
-rwxrwxrwx
git-describe.exe
44.55
KB
-rwxrwxrwx
git-diff-files.exe
44.55
KB
-rwxrwxrwx
git-diff-index.exe
44.55
KB
-rwxrwxrwx
git-diff-tree.exe
44.55
KB
-rwxrwxrwx
git-diff.exe
44.55
KB
-rwxrwxrwx
git-difftool--helper
2.44
KB
-rw-rw-rw-
git-difftool.exe
44.55
KB
-rwxrwxrwx
git-env--helper.exe
44.55
KB
-rwxrwxrwx
git-fast-export.exe
44.55
KB
-rwxrwxrwx
git-fast-import.exe
44.55
KB
-rwxrwxrwx
git-fetch-pack.exe
44.55
KB
-rwxrwxrwx
git-fetch.exe
44.55
KB
-rwxrwxrwx
git-filter-branch
15.49
KB
-rw-rw-rw-
git-fmt-merge-msg.exe
44.55
KB
-rwxrwxrwx
git-for-each-ref.exe
44.55
KB
-rwxrwxrwx
git-for-each-repo.exe
44.55
KB
-rwxrwxrwx
git-format-patch.exe
44.55
KB
-rwxrwxrwx
git-fsck-objects.exe
44.55
KB
-rwxrwxrwx
git-fsck.exe
44.55
KB
-rwxrwxrwx
git-fsmonitor--daemon.exe
44.55
KB
-rwxrwxrwx
git-gc.exe
44.55
KB
-rwxrwxrwx
git-get-tar-commit-id.exe
44.55
KB
-rwxrwxrwx
git-grep.exe
44.55
KB
-rwxrwxrwx
git-gui
687
B
-rw-rw-rw-
git-gui--askpass
1.8
KB
-rw-rw-rw-
git-gui--askyesno
1.57
KB
-rw-rw-rw-
git-gui.tcl
104.12
KB
-rw-rw-rw-
git-hash-object.exe
44.55
KB
-rwxrwxrwx
git-help.exe
44.55
KB
-rwxrwxrwx
git-hook.exe
44.55
KB
-rwxrwxrwx
git-http-backend.exe
2.05
MB
-rwxrwxrwx
git-http-fetch.exe
2.07
MB
-rwxrwxrwx
git-http-push.exe
2.08
MB
-rwxrwxrwx
git-imap-send.exe
2.08
MB
-rwxrwxrwx
git-index-pack.exe
44.55
KB
-rwxrwxrwx
git-init-db.exe
44.55
KB
-rwxrwxrwx
git-init.exe
44.55
KB
-rwxrwxrwx
git-instaweb
21.65
KB
-rw-rw-rw-
git-interpret-trailers.exe
44.55
KB
-rwxrwxrwx
git-log.exe
44.55
KB
-rwxrwxrwx
git-ls-files.exe
44.55
KB
-rwxrwxrwx
git-ls-remote.exe
44.55
KB
-rwxrwxrwx
git-ls-tree.exe
44.55
KB
-rwxrwxrwx
git-mailinfo.exe
44.55
KB
-rwxrwxrwx
git-mailsplit.exe
44.55
KB
-rwxrwxrwx
git-maintenance.exe
44.55
KB
-rwxrwxrwx
git-merge-base.exe
44.55
KB
-rwxrwxrwx
git-merge-file.exe
44.55
KB
-rwxrwxrwx
git-merge-index.exe
44.55
KB
-rwxrwxrwx
git-merge-octopus
2.42
KB
-rw-rw-rw-
git-merge-one-file
3.61
KB
-rw-rw-rw-
git-merge-ours.exe
44.55
KB
-rwxrwxrwx
git-merge-recursive.exe
44.55
KB
-rwxrwxrwx
git-merge-resolve
944
B
-rw-rw-rw-
git-merge-subtree.exe
44.55
KB
-rwxrwxrwx
git-merge-tree.exe
44.55
KB
-rwxrwxrwx
git-merge.exe
44.55
KB
-rwxrwxrwx
git-mergetool
11.29
KB
-rw-rw-rw-
git-mergetool--lib
9.69
KB
-rw-rw-rw-
git-mktag.exe
44.55
KB
-rwxrwxrwx
git-mktree.exe
44.55
KB
-rwxrwxrwx
git-multi-pack-index.exe
44.55
KB
-rwxrwxrwx
git-mv.exe
44.55
KB
-rwxrwxrwx
git-name-rev.exe
44.55
KB
-rwxrwxrwx
git-notes.exe
44.55
KB
-rwxrwxrwx
git-p4
168.59
KB
-rw-rw-rw-
git-pack-objects.exe
44.55
KB
-rwxrwxrwx
git-pack-redundant.exe
44.55
KB
-rwxrwxrwx
git-pack-refs.exe
44.55
KB
-rwxrwxrwx
git-patch-id.exe
44.55
KB
-rwxrwxrwx
git-prune-packed.exe
44.55
KB
-rwxrwxrwx
git-prune.exe
44.55
KB
-rwxrwxrwx
git-pull.exe
44.55
KB
-rwxrwxrwx
git-push.exe
44.55
KB
-rwxrwxrwx
git-quiltimport
3.61
KB
-rw-rw-rw-
git-range-diff.exe
44.55
KB
-rwxrwxrwx
git-read-tree.exe
44.55
KB
-rwxrwxrwx
git-rebase.exe
44.55
KB
-rwxrwxrwx
git-receive-pack.exe
44.55
KB
-rwxrwxrwx
git-reflog.exe
44.55
KB
-rwxrwxrwx
git-remote-ext.exe
44.55
KB
-rwxrwxrwx
git-remote-fd.exe
44.55
KB
-rwxrwxrwx
git-remote-ftp.exe
2.09
MB
-rwxrwxrwx
git-remote-ftps.exe
2.09
MB
-rwxrwxrwx
git-remote-http.exe
2.09
MB
-rwxrwxrwx
git-remote-https.exe
2.09
MB
-rwxrwxrwx
git-remote.exe
44.55
KB
-rwxrwxrwx
git-repack.exe
44.55
KB
-rwxrwxrwx
git-replace.exe
44.55
KB
-rwxrwxrwx
git-request-pull
4.03
KB
-rw-rw-rw-
git-rerere.exe
44.55
KB
-rwxrwxrwx
git-reset.exe
44.55
KB
-rwxrwxrwx
git-restore.exe
44.55
KB
-rwxrwxrwx
git-rev-list.exe
44.55
KB
-rwxrwxrwx
git-rev-parse.exe
44.55
KB
-rwxrwxrwx
git-revert.exe
44.55
KB
-rwxrwxrwx
git-rm.exe
44.55
KB
-rwxrwxrwx
git-send-email
62.44
KB
-rw-rw-rw-
git-send-pack.exe
44.55
KB
-rwxrwxrwx
git-sh-i18n
1.67
KB
-rw-rw-rw-
git-sh-i18n--envsubst.exe
2.04
MB
-rwxrwxrwx
git-sh-setup
8.92
KB
-rw-rw-rw-
git-shortlog.exe
44.55
KB
-rwxrwxrwx
git-show-branch.exe
44.55
KB
-rwxrwxrwx
git-show-index.exe
44.55
KB
-rwxrwxrwx
git-show-ref.exe
44.55
KB
-rwxrwxrwx
git-show.exe
44.55
KB
-rwxrwxrwx
git-sparse-checkout.exe
44.55
KB
-rwxrwxrwx
git-stage.exe
44.55
KB
-rwxrwxrwx
git-stash.exe
44.55
KB
-rwxrwxrwx
git-status.exe
44.55
KB
-rwxrwxrwx
git-stripspace.exe
44.55
KB
-rwxrwxrwx
git-submodule
11.02
KB
-rw-rw-rw-
git-submodule--helper.exe
44.55
KB
-rwxrwxrwx
git-subtree
23.01
KB
-rw-rw-rw-
git-svn
64.26
KB
-rw-rw-rw-
git-switch.exe
44.55
KB
-rwxrwxrwx
git-symbolic-ref.exe
44.55
KB
-rwxrwxrwx
git-tag.exe
44.55
KB
-rwxrwxrwx
git-unpack-file.exe
44.55
KB
-rwxrwxrwx
git-unpack-objects.exe
44.55
KB
-rwxrwxrwx
git-update
218
B
-rw-rw-rw-
git-update-index.exe
44.55
KB
-rwxrwxrwx
git-update-ref.exe
44.55
KB
-rwxrwxrwx
git-update-server-info.exe
44.55
KB
-rwxrwxrwx
git-upload-archive.exe
44.55
KB
-rwxrwxrwx
git-upload-pack.exe
44.55
KB
-rwxrwxrwx
git-var.exe
44.55
KB
-rwxrwxrwx
git-verify-commit.exe
44.55
KB
-rwxrwxrwx
git-verify-pack.exe
44.55
KB
-rwxrwxrwx
git-verify-tag.exe
44.55
KB
-rwxrwxrwx
git-web--browse
4.3
KB
-rw-rw-rw-
git-whatchanged.exe
44.55
KB
-rwxrwxrwx
git-worktree.exe
44.55
KB
-rwxrwxrwx
git-write-tree.exe
44.55
KB
-rwxrwxrwx
git.exe
3.43
MB
-rwxrwxrwx
headless-git.exe
32.05
KB
-rwxrwxrwx
libbrotlicommon.dll
140.04
KB
-rw-rw-rw-
libbrotlidec.dll
50.64
KB
-rw-rw-rw-
libbz2-1.dll
96.82
KB
-rw-rw-rw-
libcares-5.dll
122.1
KB
-rw-rw-rw-
libcrypto-1_1-x64.dll
2.67
MB
-rw-rw-rw-
libcurl-4.dll
664.15
KB
-rw-rw-rw-
libexpat-1.dll
198.82
KB
-rw-rw-rw-
libffi-8.dll
31.14
KB
-rw-rw-rw-
libgcc_s_seh-1.dll
105.17
KB
-rw-rw-rw-
libgmp-10.dll
641.51
KB
-rw-rw-rw-
libhogweed-6.dll
268.31
KB
-rw-rw-rw-
libiconv-2.dll
1.06
MB
-rw-rw-rw-
libidn2-0.dll
230.63
KB
-rw-rw-rw-
libintl-8.dll
133.52
KB
-rw-rw-rw-
libjansson-4.dll
77.08
KB
-rw-rw-rw-
libjemalloc.dll
674.46
KB
-rw-rw-rw-
liblzma-5.dll
147.65
KB
-rw-rw-rw-
libnettle-8.dll
308.12
KB
-rw-rw-rw-
libnghttp2-14.dll
185.59
KB
-rw-rw-rw-
libp11-kit-0.dll
1.03
MB
-rw-rw-rw-
libpcre-1.dll
275.09
KB
-rw-rw-rw-
libpcre2-8-0.dll
624.85
KB
-rw-rw-rw-
libpcreposix-0.dll
40.77
KB
-rw-rw-rw-
libssh2-1.dll
263.79
KB
-rw-rw-rw-
libssl-1_1-x64.dll
539.65
KB
-rw-rw-rw-
libssp-0.dll
42.41
KB
-rw-rw-rw-
libstdc++-6.dll
1.93
MB
-rw-rw-rw-
libtasn1-6.dll
101.04
KB
-rw-rw-rw-
libtre-5.dll
90.15
KB
-rw-rw-rw-
libunistring-2.dll
1.84
MB
-rw-rw-rw-
libwinpthread-1.dll
56.75
KB
-rw-rw-rw-
libxml2-2.dll
1.28
MB
-rw-rw-rw-
libzstd.dll
810.89
KB
-rw-rw-rw-
tcl86.dll
1.6
MB
-rw-rw-rw-
tk86.dll
1.44
MB
-rw-rw-rw-
zlib1.dll
116.24
KB
-rw-rw-rw-
Delete
Unzip
Zip
${this.title}
Close
Code Editor : git-subtree
#!/bin/sh # # git-subtree.sh: split/join git repositories in subdirectories of this one # # Copyright (C) 2009 Avery Pennarun <apenwarr@gmail.com> # if test -z "$GIT_EXEC_PATH" || ! test -f "$GIT_EXEC_PATH/git-sh-setup" || { test "${PATH#"${GIT_EXEC_PATH}:"}" = "$PATH" && test ! "$GIT_EXEC_PATH" -ef "${PATH%%:*}" 2>/dev/null } then basename=${0##*[/\\]} echo >&2 'It looks like either your git installation or your' echo >&2 'git-subtree installation is broken.' echo >&2 echo >&2 "Tips:" echo >&2 " - If \`git --exec-path\` does not print the correct path to" echo >&2 " your git install directory, then set the GIT_EXEC_PATH" echo >&2 " environment variable to the correct directory." echo >&2 " - Make sure that your \`$basename\` file is either in your" echo >&2 " PATH or in your git exec path (\`$(git --exec-path)\`)." echo >&2 " - You should run git-subtree as \`git ${basename#git-}\`," echo >&2 " not as \`$basename\`." >&2 exit 126 fi OPTS_SPEC="\ git subtree add --prefix=<prefix> <commit> git subtree add --prefix=<prefix> <repository> <ref> git subtree merge --prefix=<prefix> <commit> git subtree split --prefix=<prefix> [<commit>] git subtree pull --prefix=<prefix> <repository> <ref> git subtree push --prefix=<prefix> <repository> <refspec> -- h,help show the help q quiet d show debug messages P,prefix= the name of the subdir to split out options for 'split' (also: 'push') annotate= add a prefix to commit message of new commits 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' and 'merge' (also: 'pull', 'split --rejoin', and 'push --rejoin') squash merge subtree changes as a single commit m,message= use the given message as the commit message for the merge commit " indent=0 # Usage: debug [MSG...] debug () { if test -n "$arg_debug" then printf "%$(($indent * 2))s%s\n" '' "$*" >&2 fi } # Usage: progress [MSG...] progress () { if test -z "$GIT_QUIET" then if test -z "$arg_debug" then # Debug mode is off. # # Print one progress line that we keep updating (use # "\r" to return to the beginning of the line, rather # than "\n" to start a new line). This only really # works when stderr is a terminal. printf "%s\r" "$*" >&2 else # Debug mode is on. The `debug` function is regularly # printing to stderr. # # Don't do the one-line-with-"\r" thing, because on a # terminal the debug output would overwrite and hide the # progress output. Add a "progress:" prefix to make the # progress output and the debug output easy to # distinguish. This ensures maximum readability whether # stderr is a terminal or a file. printf "progress: %s\n" "$*" >&2 fi fi } # Usage: assert CMD... assert () { if ! "$@" then die "assertion failed: $*" fi } main () { if test $# -eq 0 then set -- -h fi set_args="$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)" eval "$set_args" . git-sh-setup require_work_tree # First figure out the command and whether we use --rejoin, so # that we can provide more helpful validation when we do the # "real" flag parsing. arg_split_rejoin= allow_split= allow_addmerge= while test $# -gt 0 do opt="$1" shift case "$opt" in --annotate|-b|-P|-m|--onto) shift ;; --rejoin) arg_split_rejoin=1 ;; --no-rejoin) arg_split_rejoin= ;; --) break ;; esac done arg_command=$1 case "$arg_command" in add|merge|pull) allow_addmerge=1 ;; split|push) allow_split=1 allow_addmerge=$arg_split_rejoin ;; *) die "Unknown command '$arg_command'" ;; esac # Reset the arguments array for "real" flag parsing. eval "$set_args" # Begin "real" flag parsing. arg_debug= arg_prefix= arg_split_branch= arg_split_onto= arg_split_ignore_joins= arg_split_annotate= arg_addmerge_squash= arg_addmerge_message= while test $# -gt 0 do opt="$1" shift case "$opt" in -q) GIT_QUIET=1 ;; -d) arg_debug=1 ;; --annotate) test -n "$allow_split" || die "The '$opt' flag does not make sense with 'git subtree $arg_command'." arg_split_annotate="$1" shift ;; --no-annotate) test -n "$allow_split" || die "The '$opt' flag does not make sense with 'git subtree $arg_command'." arg_split_annotate= ;; -b) test -n "$allow_split" || die "The '$opt' flag does not make sense with 'git subtree $arg_command'." arg_split_branch="$1" shift ;; -P) arg_prefix="${1%/}" shift ;; -m) test -n "$allow_addmerge" || die "The '$opt' flag does not make sense with 'git subtree $arg_command'." arg_addmerge_message="$1" shift ;; --no-prefix) arg_prefix= ;; --onto) test -n "$allow_split" || die "The '$opt' flag does not make sense with 'git subtree $arg_command'." arg_split_onto="$1" shift ;; --no-onto) test -n "$allow_split" || die "The '$opt' flag does not make sense with 'git subtree $arg_command'." arg_split_onto= ;; --rejoin) test -n "$allow_split" || die "The '$opt' flag does not make sense with 'git subtree $arg_command'." ;; --no-rejoin) test -n "$allow_split" || die "The '$opt' flag does not make sense with 'git subtree $arg_command'." ;; --ignore-joins) test -n "$allow_split" || die "The '$opt' flag does not make sense with 'git subtree $arg_command'." arg_split_ignore_joins=1 ;; --no-ignore-joins) test -n "$allow_split" || die "The '$opt' flag does not make sense with 'git subtree $arg_command'." arg_split_ignore_joins= ;; --squash) test -n "$allow_addmerge" || die "The '$opt' flag does not make sense with 'git subtree $arg_command'." arg_addmerge_squash=1 ;; --no-squash) test -n "$allow_addmerge" || die "The '$opt' flag does not make sense with 'git subtree $arg_command'." arg_addmerge_squash= ;; --) break ;; *) die "Unexpected option: $opt" ;; esac done shift if test -z "$arg_prefix" then die "You must provide the --prefix option." fi case "$arg_command" in add) test -e "$arg_prefix" && die "prefix '$arg_prefix' already exists." ;; *) test -e "$arg_prefix" || die "'$arg_prefix' does not exist; use 'git subtree add'" ;; esac dir="$(dirname "$arg_prefix/.")" debug "command: {$arg_command}" debug "quiet: {$GIT_QUIET}" debug "dir: {$dir}" debug "opts: {$*}" debug "cmd_$arg_command" "$@" } # Usage: cache_setup cache_setup () { assert test $# = 0 cachedir="$GIT_DIR/subtree-cache/$$" rm -rf "$cachedir" || die "Can't delete old cachedir: $cachedir" mkdir -p "$cachedir" || die "Can't create new cachedir: $cachedir" mkdir -p "$cachedir/notree" || die "Can't create new cachedir: $cachedir/notree" debug "Using cachedir: $cachedir" >&2 } # Usage: cache_get [REVS...] cache_get () { for oldrev in "$@" do if test -r "$cachedir/$oldrev" then read newrev <"$cachedir/$oldrev" echo $newrev fi done } # Usage: cache_miss [REVS...] cache_miss () { for oldrev in "$@" do if ! test -r "$cachedir/$oldrev" then echo $oldrev fi done } # Usage: check_parents [REVS...] check_parents () { missed=$(cache_miss "$@") || exit $? local indent=$(($indent + 1)) for miss in $missed do if ! test -r "$cachedir/notree/$miss" then debug "incorrect order: $miss" process_split_commit "$miss" "" fi done } # Usage: set_notree REV set_notree () { assert test $# = 1 echo "1" > "$cachedir/notree/$1" } # Usage: cache_set OLDREV NEWREV cache_set () { assert test $# = 2 oldrev="$1" newrev="$2" if test "$oldrev" != "latest_old" && test "$oldrev" != "latest_new" && test -e "$cachedir/$oldrev" then die "cache for $oldrev already exists!" fi echo "$newrev" >"$cachedir/$oldrev" } # Usage: rev_exists REV rev_exists () { assert test $# = 1 if git rev-parse "$1" >/dev/null 2>&1 then return 0 else return 1 fi } # Usage: try_remove_previous REV # # If a commit doesn't have a parent, this might not work. But we only want # to remove the parent from the rev-list, and since it doesn't exist, it won't # be there anyway, so do nothing in that case. try_remove_previous () { assert test $# = 1 if rev_exists "$1^" then echo "^$1^" fi } # Usage: find_latest_squash DIR find_latest_squash () { assert test $# = 1 debug "Looking for latest squash ($dir)..." local indent=$(($indent + 1)) dir="$1" sq= main= sub= git log --grep="^git-subtree-dir: $dir/*\$" \ --no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' HEAD | while read a b junk do debug "$a $b $junk" debug "{{$sq/$main/$sub}}" case "$a" in START) sq="$b" ;; git-subtree-mainline:) main="$b" ;; git-subtree-split:) sub="$(git rev-parse "$b^{commit}")" || die "could not rev-parse split hash $b from commit $sq" ;; END) if test -n "$sub" then if test -n "$main" then # a rejoin commit? # Pretend its sub was a squash. sq=$(git rev-parse --verify "$sq^2") || die fi debug "Squash found: $sq $sub" echo "$sq" "$sub" break fi sq= main= sub= ;; esac done || exit $? } # Usage: find_existing_splits DIR REV find_existing_splits () { assert test $# = 2 debug "Looking for prior splits..." local indent=$(($indent + 1)) dir="$1" rev="$2" main= sub= local grep_format="^git-subtree-dir: $dir/*\$" if test -n "$arg_split_ignore_joins" then grep_format="^Add '$dir/' from commit '" fi git log --grep="$grep_format" \ --no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' "$rev" | while read a b junk do case "$a" in START) sq="$b" ;; git-subtree-mainline:) main="$b" ;; git-subtree-split:) sub="$(git rev-parse "$b^{commit}")" || die "could not rev-parse split hash $b from commit $sq" ;; END) debug "Main is: '$main'" if test -z "$main" -a -n "$sub" then # squash commits refer to a subtree debug " Squash: $sq from $sub" cache_set "$sq" "$sub" fi if test -n "$main" -a -n "$sub" then debug " Prior: $main -> $sub" cache_set $main $sub cache_set $sub $sub try_remove_previous "$main" try_remove_previous "$sub" fi main= sub= ;; esac done || exit $? } # Usage: copy_commit REV TREE FLAGS_STR copy_commit () { assert test $# = 3 # We're going to set some environment vars here, so # do it in a subshell to get rid of them safely later debug copy_commit "{$1}" "{$2}" "{$3}" git log -1 --no-show-signature --pretty=format:'%an%n%ae%n%aD%n%cn%n%ce%n%cD%n%B' "$1" | ( read GIT_AUTHOR_NAME read GIT_AUTHOR_EMAIL read GIT_AUTHOR_DATE read GIT_COMMITTER_NAME read GIT_COMMITTER_EMAIL read GIT_COMMITTER_DATE export GIT_AUTHOR_NAME \ GIT_AUTHOR_EMAIL \ GIT_AUTHOR_DATE \ GIT_COMMITTER_NAME \ GIT_COMMITTER_EMAIL \ GIT_COMMITTER_DATE ( printf "%s" "$arg_split_annotate" cat ) | git commit-tree "$2" $3 # reads the rest of stdin ) || die "Can't copy commit $1" } # Usage: add_msg DIR LATEST_OLD LATEST_NEW add_msg () { assert test $# = 3 dir="$1" latest_old="$2" latest_new="$3" if test -n "$arg_addmerge_message" then commit_message="$arg_addmerge_message" else commit_message="Add '$dir/' from commit '$latest_new'" fi if test -n "$arg_split_rejoin" then # If this is from a --rejoin, then rejoin_msg has # already inserted the `git-subtree-xxx:` tags echo "$commit_message" return fi cat <<-EOF $commit_message git-subtree-dir: $dir git-subtree-mainline: $latest_old git-subtree-split: $latest_new EOF } # Usage: add_squashed_msg REV DIR add_squashed_msg () { assert test $# = 2 if test -n "$arg_addmerge_message" then echo "$arg_addmerge_message" else echo "Merge commit '$1' as '$2'" fi } # Usage: rejoin_msg DIR LATEST_OLD LATEST_NEW rejoin_msg () { assert test $# = 3 dir="$1" latest_old="$2" latest_new="$3" if test -n "$arg_addmerge_message" then commit_message="$arg_addmerge_message" else commit_message="Split '$dir/' into commit '$latest_new'" fi cat <<-EOF $commit_message git-subtree-dir: $dir git-subtree-mainline: $latest_old git-subtree-split: $latest_new EOF } # Usage: squash_msg DIR OLD_SUBTREE_COMMIT NEW_SUBTREE_COMMIT squash_msg () { assert test $# = 3 dir="$1" oldsub="$2" newsub="$3" newsub_short=$(git rev-parse --short "$newsub") if test -n "$oldsub" then oldsub_short=$(git rev-parse --short "$oldsub") echo "Squashed '$dir/' changes from $oldsub_short..$newsub_short" echo git log --no-show-signature --pretty=tformat:'%h %s' "$oldsub..$newsub" git log --no-show-signature --pretty=tformat:'REVERT: %h %s' "$newsub..$oldsub" else echo "Squashed '$dir/' content from commit $newsub_short" fi echo echo "git-subtree-dir: $dir" echo "git-subtree-split: $newsub" } # Usage: toptree_for_commit COMMIT toptree_for_commit () { assert test $# = 1 commit="$1" git rev-parse --verify "$commit^{tree}" || exit $? } # Usage: subtree_for_commit COMMIT DIR subtree_for_commit () { assert test $# = 2 commit="$1" dir="$2" git ls-tree "$commit" -- "$dir" | while read mode type tree name do assert test "$name" = "$dir" assert test "$type" = "tree" -o "$type" = "commit" test "$type" = "commit" && continue # ignore submodules echo $tree break done || exit $? } # Usage: tree_changed TREE [PARENTS...] tree_changed () { assert test $# -gt 0 tree=$1 shift if test $# -ne 1 then return 0 # weird parents, consider it changed else ptree=$(toptree_for_commit $1) || exit $? if test "$ptree" != "$tree" then return 0 # changed else return 1 # not changed fi fi } # Usage: new_squash_commit OLD_SQUASHED_COMMIT OLD_NONSQUASHED_COMMIT NEW_NONSQUASHED_COMMIT new_squash_commit () { assert test $# = 3 old="$1" oldsub="$2" newsub="$3" tree=$(toptree_for_commit $newsub) || exit $? if test -n "$old" then squash_msg "$dir" "$oldsub" "$newsub" | git commit-tree "$tree" -p "$old" || exit $? else squash_msg "$dir" "" "$newsub" | git commit-tree "$tree" || exit $? fi } # Usage: copy_or_skip REV TREE NEWPARENTS copy_or_skip () { assert test $# = 3 rev="$1" tree="$2" newparents="$3" assert test -n "$tree" identical= nonidentical= p= gotparents= copycommit= for parent in $newparents do ptree=$(toptree_for_commit $parent) || exit $? test -z "$ptree" && continue if test "$ptree" = "$tree" then # an identical parent could be used in place of this rev. if test -n "$identical" then # if a previous identical parent was found, check whether # one is already an ancestor of the other mergebase=$(git merge-base $identical $parent) if test "$identical" = "$mergebase" then # current identical commit is an ancestor of parent identical="$parent" elif test "$parent" != "$mergebase" then # no common history; commit must be copied copycommit=1 fi else # first identical parent detected identical="$parent" fi else nonidentical="$parent" fi # sometimes both old parents map to the same newparent; # eliminate duplicates is_new=1 for gp in $gotparents do if test "$gp" = "$parent" then is_new= break fi done if test -n "$is_new" then gotparents="$gotparents $parent" p="$p -p $parent" fi done if test -n "$identical" && test -n "$nonidentical" then extras=$(git rev-list --count $identical..$nonidentical) if test "$extras" -ne 0 then # we need to preserve history along the other branch copycommit=1 fi fi if test -n "$identical" && test -z "$copycommit" then echo $identical else copy_commit "$rev" "$tree" "$p" || exit $? fi } # Usage: ensure_clean ensure_clean () { assert test $# = 0 if ! git diff-index HEAD --exit-code --quiet 2>&1 then die "Working tree has modifications. Cannot add." fi if ! git diff-index --cached HEAD --exit-code --quiet 2>&1 then die "Index has modifications. Cannot add." fi } # Usage: ensure_valid_ref_format REF ensure_valid_ref_format () { assert test $# = 1 git check-ref-format "refs/heads/$1" || die "'$1' does not look like a ref" } # Usage: process_split_commit REV PARENTS process_split_commit () { assert test $# = 2 local rev="$1" local parents="$2" if test $indent -eq 0 then revcount=$(($revcount + 1)) else # processing commit without normal parent information; # fetch from repo parents=$(git rev-parse "$rev^@") extracount=$(($extracount + 1)) fi progress "$revcount/$revmax ($createcount) [$extracount]" debug "Processing commit: $rev" local indent=$(($indent + 1)) exists=$(cache_get "$rev") || exit $? if test -n "$exists" then debug "prior: $exists" return fi createcount=$(($createcount + 1)) debug "parents: $parents" check_parents $parents newparents=$(cache_get $parents) || exit $? debug "newparents: $newparents" tree=$(subtree_for_commit "$rev" "$dir") || exit $? debug "tree is: $tree" # ugly. is there no better way to tell if this is a subtree # vs. a mainline commit? Does it matter? if test -z "$tree" then set_notree "$rev" if test -n "$newparents" then cache_set "$rev" "$rev" fi return fi newrev=$(copy_or_skip "$rev" "$tree" "$newparents") || exit $? debug "newrev is: $newrev" cache_set "$rev" "$newrev" cache_set latest_new "$newrev" cache_set latest_old "$rev" } # Usage: cmd_add REV # Or: cmd_add REPOSITORY REF cmd_add () { ensure_clean if test $# -eq 1 then git rev-parse -q --verify "$1^{commit}" >/dev/null || die "'$1' does not refer to a commit" cmd_add_commit "$@" elif test $# -eq 2 then # Technically we could accept a refspec here but we're # just going to turn around and add FETCH_HEAD under the # specified directory. Allowing a refspec might be # misleading because we won't do anything with any other # branches fetched via the refspec. ensure_valid_ref_format "$2" cmd_add_repository "$@" else say >&2 "error: parameters were '$*'" die "Provide either a commit or a repository and commit." fi } # Usage: cmd_add_repository REPOSITORY REFSPEC cmd_add_repository () { assert test $# = 2 echo "git fetch" "$@" repository=$1 refspec=$2 git fetch "$@" || exit $? cmd_add_commit FETCH_HEAD } # Usage: cmd_add_commit REV cmd_add_commit () { # The rev has already been validated by cmd_add(), we just # need to normalize it. assert test $# = 1 rev=$(git rev-parse --verify "$1^{commit}") || exit $? debug "Adding $dir as '$rev'..." if test -z "$arg_split_rejoin" then # Only bother doing this if this is a genuine 'add', # not a synthetic 'add' from '--rejoin'. git read-tree --prefix="$dir" $rev || exit $? fi git checkout -- "$dir" || exit $? tree=$(git write-tree) || exit $? headrev=$(git rev-parse HEAD) || exit $? if test -n "$headrev" && test "$headrev" != "$rev" then headp="-p $headrev" else headp= fi if test -n "$arg_addmerge_squash" then rev=$(new_squash_commit "" "" "$rev") || exit $? commit=$(add_squashed_msg "$rev" "$dir" | git commit-tree "$tree" $headp -p "$rev") || exit $? else revp=$(peel_committish "$rev") || exit $? commit=$(add_msg "$dir" $headrev "$rev" | git commit-tree "$tree" $headp -p "$revp") || exit $? fi git reset "$commit" || exit $? say >&2 "Added dir '$dir'" } # Usage: cmd_split [REV] cmd_split () { if test $# -eq 0 then rev=$(git rev-parse HEAD) elif test $# -eq 1 then rev=$(git rev-parse -q --verify "$1^{commit}") || die "'$1' does not refer to a commit" else die "You must provide exactly one revision. Got: '$*'" fi if test -n "$arg_split_rejoin" then ensure_clean fi debug "Splitting $dir..." cache_setup || exit $? if test -n "$arg_split_onto" then debug "Reading history for --onto=$arg_split_onto..." git rev-list $arg_split_onto | while read rev do # the 'onto' history is already just the subdir, so # any parent we find there can be used verbatim debug "cache: $rev" cache_set "$rev" "$rev" done || exit $? fi unrevs="$(find_existing_splits "$dir" "$rev")" || exit $? # We can't restrict rev-list to only $dir here, because some of our # parents have the $dir contents the root, and those won't match. # (and rev-list --follow doesn't seem to solve this) grl='git rev-list --topo-order --reverse --parents $rev $unrevs' revmax=$(eval "$grl" | wc -l) revcount=0 createcount=0 extracount=0 eval "$grl" | while read rev parents do process_split_commit "$rev" "$parents" done || exit $? latest_new=$(cache_get latest_new) || exit $? if test -z "$latest_new" then die "No new revisions were found" fi if test -n "$arg_split_rejoin" then debug "Merging split branch into HEAD..." latest_old=$(cache_get latest_old) || exit $? arg_addmerge_message="$(rejoin_msg "$dir" "$latest_old" "$latest_new")" || exit $? if test -z "$(find_latest_squash "$dir")" then cmd_add "$latest_new" >&2 || exit $? else cmd_merge "$latest_new" >&2 || exit $? fi fi if test -n "$arg_split_branch" then if rev_exists "refs/heads/$arg_split_branch" then if ! git merge-base --is-ancestor "$arg_split_branch" "$latest_new" then die "Branch '$arg_split_branch' is not an ancestor of commit '$latest_new'." fi action='Updated' else action='Created' fi git update-ref -m 'subtree split' \ "refs/heads/$arg_split_branch" "$latest_new" || exit $? say >&2 "$action branch '$arg_split_branch'" fi echo "$latest_new" exit 0 } # Usage: cmd_merge REV cmd_merge () { test $# -eq 1 || die "You must provide exactly one revision. Got: '$*'" rev=$(git rev-parse -q --verify "$1^{commit}") || die "'$1' does not refer to a commit" ensure_clean if test -n "$arg_addmerge_squash" then first_split="$(find_latest_squash "$dir")" || exit $? if test -z "$first_split" then die "Can't squash-merge: '$dir' was never added." fi set $first_split old=$1 sub=$2 if test "$sub" = "$rev" then say >&2 "Subtree is already at commit $rev." exit 0 fi new=$(new_squash_commit "$old" "$sub" "$rev") || exit $? debug "New squash commit: $new" rev="$new" fi if test -n "$arg_addmerge_message" then git merge --no-ff -Xsubtree="$arg_prefix" \ --message="$arg_addmerge_message" "$rev" else git merge --no-ff -Xsubtree="$arg_prefix" $rev fi } # Usage: cmd_pull REPOSITORY REMOTEREF cmd_pull () { if test $# -ne 2 then die "You must provide <repository> <ref>" fi ensure_clean ensure_valid_ref_format "$2" git fetch "$@" || exit $? cmd_merge FETCH_HEAD } # Usage: cmd_push REPOSITORY [+][LOCALREV:]REMOTEREF cmd_push () { if test $# -ne 2 then die "You must provide <repository> <refspec>" fi if test -e "$dir" then repository=$1 refspec=${2#+} remoteref=${refspec#*:} if test "$remoteref" = "$refspec" then localrevname_presplit=HEAD else localrevname_presplit=${refspec%%:*} fi ensure_valid_ref_format "$remoteref" localrev_presplit=$(git rev-parse -q --verify "$localrevname_presplit^{commit}") || die "'$localrevname_presplit' does not refer to a commit" echo "git push using: " "$repository" "$refspec" localrev=$(cmd_split "$localrev_presplit") || die git push "$repository" "$localrev":"refs/heads/$remoteref" else die "'$dir' must already exist. Try 'git subtree add'." fi } main "$@"
Close