Skip to content
Snippets Groups Projects

git history-move

  • Clone with SSH
  • Clone with HTTPS
  • Embed
  • Share
    The snippet can be accessed without any authentication.
    Authored by Ingo Meyer
    Usage: git history-move [-d] [-r file regex] <target-directory> [<rev-list options>]
    
    A helper script for `git filter-branch` for moving selected files to another directory in Git history.
    
    positional arguments:
      <target-directory>   The target directory the selected files will be moved to.
      <rev-list options>   Arguments for `git rev-list`. All positive refs included by these options are rewritten.
                           See `man git-filter-branch` for more details.
    
    optional arguments:
      -d   Dry run, only print files that would be moved.
      -r   Regex filter for files being moved, defaults to '.*' (matches every string).
           Hint: By default the regex will match every substring of a given file path,
                 use '^{regex}$' to match the complete string instead.
    Edited
    git-history-move.sh 2.68 KiB
    #!/bin/bash
    
    print_usage () {
        echo "Usage: git history-move [-d] [-r file regex] <target-directory> [<rev-list options>]"
        echo
        echo "A helper script for \`git filter-branch\` for moving selected files to another directory in Git history."
        echo
        echo "positional arguments:"
        echo "  <target-directory>   The target directory the selected files will be moved to."
        echo "  <rev-list options>   Arguments for \`git rev-list\`. All positive refs included by these options are rewritten."
        echo "                       See \`man git-filter-branch\` for more details."
    
        echo
        echo "optional arguments:"
        echo "  -d   Dry run, only print files that would be moved."
        echo "  -r   Regex filter for files being moved, defaults to '.*' (matches every string)."
        echo "       Hint: By default the regex will match every substring of a given file path,"
        echo "             use '^{regex}$' to match the complete string instead."
    }
    
    parse_options () {
        DRY_RUN=0
        FILE_REGEX=".*"
        while getopts ":dr:" opt; do
            case ${opt} in
                d)
                    DRY_RUN=1
                    ;;
                r)
                    FILE_REGEX="${OPTARG}"
                    ;;
                :)
                    >&2 echo "Option '-${OPTARG}' requires an argument."
                    exit 1
                    ;;
                \?)
                    >&2 echo "Invalid option: '-${OPTARG}'"
                    print_usage
                    exit 1
                    ;;
                *)
                    print_usage
                    exit 1
                    ;;
            esac
        done
        shift $((OPTIND-1))
        TARGET_DIR="$1"
        if [[ "${TARGET_DIR}" == "" ]]; then
            >&2 echo "Please specify a target directory!"
            print_usage
            exit 1
        fi
        shift
        REMAINING_ARGS=( "$@" )
    }
    
    filter_git_repository () {
        local TMP_SCRIPT_DIR RETURN_CODE
    
        TMP_SCRIPT_DIR="$(mktemp -d)" || return 1
        cat <<- EOF > "${TMP_SCRIPT_DIR}/filter.sh"
    		#!/bin/bash
    		if (( ${DRY_RUN} )); then
    		    echo
    		fi
    		git ls-tree --name-only "\${GIT_COMMIT}" | while read -r FILE; do
    		    if [[ ! "\${FILE}" =~ ${FILE_REGEX} ]]; then
    		        continue
    		    fi
    		    if (( ${DRY_RUN} )); then
    		        echo " -> Would move \${FILE} to ${TARGET_DIR}/"
    		    else
    		        if [[ ! -d "${TARGET_DIR}" ]]; then
    		            mkdir -p "${TARGET_DIR}"
    		        fi
    		        mv "\${FILE}" "${TARGET_DIR}/"
    		    fi
    		done
    	EOF
        chmod +x "${TMP_SCRIPT_DIR}/filter.sh" && \
        git filter-branch --prune-empty --tree-filter "${TMP_SCRIPT_DIR}/filter.sh" "${REMAINING_ARGS[@]}"
        RETURN_CODE="$?"
        rm -rf "${TMP_SCRIPT_DIR}"
        return "${RETURN_CODE}"
    }
    
    main () {
        parse_options "$@" && \
        filter_git_repository
    }
    
    main "$@"
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Finish editing this message first!
    Please register or to comment