Do a “git export” (like “svn export”)?

后端 未结 30 2909
暖寄归人
暖寄归人 2020-11-21 22:33

I\'ve been wondering whether there is a good \"git export\" solution that creates a copy of a tree without the .git repository directory. There are at least thr

30条回答
  •  难免孤独
    2020-11-21 22:42

    Bash-implementation of git-export.

    I have segmented the .empty file creation and removal processes on their own function, with the purpose of re-using them in the 'git-archive' implementation (will be posted later on).

    I have also added the '.gitattributes' file to the process in order to remove un-wanted files from the target export folder. Included verbosity to the process while making the 'git-export' function more efficient.

    EMPTY_FILE=".empty";

    function create_empty () {
    ## Processing path (target-dir):
        TRG_PATH="${1}";
    ## Component(s):
        EXCLUDE_DIR=".git";
    echo -en "\nAdding '${EMPTY_FILE}' files to empty folder(s): ...";
        find ${TRG_PATH} -not -path "*/${EXCLUDE_DIR}/*" -type d -empty -exec touch {}/${EMPTY_FILE} \;
    #echo "done.";
    ## Purging SRC/TRG_DIRs variable(s):
        unset TRG_PATH EMPTY_FILE EXCLUDE_DIR;
        return 0;
      }
    
    declare -a GIT_EXCLUDE;
    function load_exclude () {
        SRC_PATH="${1}";
        ITEMS=0; while read LINE; do
    #      echo -e "Line [${ITEMS}]: '${LINE%%\ *}'";
          GIT_EXCLUDE[((ITEMS++))]=${LINE%%\ *};
        done < ${SRC_PATH}/.gitattributes;
        GIT_EXCLUDE[${ITEMS}]="${EMPTY_FILE}";
    ## Purging variable(s):
        unset SRC_PATH ITEMS;
        return 0;
      }
    
    function purge_empty () {
    ## Processing path (Source/Target-dir):
        SRC_PATH="${1}";
        TRG_PATH="${2}";
    echo -e "\nPurging Git-Specific component(s): ... ";
        find ${SRC_PATH} -type f -name ${EMPTY_FILE} -exec /bin/rm '{}' \;
        for xRULE in ${GIT_EXCLUDE[@]}; do
    echo -en "    '${TRG_PATH}/{${xRULE}}' files ... ";
          find ${TRG_PATH} -type f -name "${xRULE}" -exec /bin/rm -rf '{}' \;
    echo "done.'";
        done;
    echo -e "done.\n"
    ## Purging SRC/TRG_PATHs variable(s):
        unset SRC_PATH; unset TRG_PATH;
        return 0;
      }
    
    function git-export () {
        TRG_DIR="${1}"; SRC_DIR="${2}";
        if [ -z "${SRC_DIR}" ]; then SRC_DIR="${PWD}"; fi
        load_exclude "${SRC_DIR}";
    ## Dynamically added '.empty' files to the Git-Structure:
        create_empty "${SRC_DIR}";
        GIT_COMMIT="Including '${EMPTY_FILE}' files into Git-Index container."; #echo -e "\n${GIT_COMMIT}";
        git add .; git commit --quiet --all --verbose --message "${GIT_COMMIT}";
        if [ "${?}" -eq 0 ]; then echo " done."; fi
        /bin/rm -rf ${TRG_DIR} && mkdir -p "${TRG_DIR}";
    echo -en "\nChecking-Out Index component(s): ... ";
        git checkout-index --prefix=${TRG_DIR}/ -q -f -a
    ## Reset: --mixed = reset HEAD and index:
        if [ "${?}" -eq 0 ]; then
    echo "done."; echo -en "Resetting HEAD and Index: ... ";
            git reset --soft HEAD^;
            if [ "${?}" -eq 0 ]; then
    echo "done.";
    ## Purging Git-specific components and '.empty' files from Target-Dir:
                purge_empty "${SRC_DIR}" "${TRG_DIR}"
              else echo "failed.";
            fi
    ## Archiving exported-content:
    echo -en "Archiving Checked-Out component(s): ... ";
            if [ -f "${TRG_DIR}.tgz" ]; then /bin/rm ${TRG_DIR}.tgz; fi
            cd ${TRG_DIR} && tar -czf ${TRG_DIR}.tgz ./; cd ${SRC_DIR}
    echo "done.";
    ## Listing *.tgz file attributes:
    ## Warning: Un-TAR this file to a specific directory:
            ls -al ${TRG_DIR}.tgz
          else echo "failed.";
        fi
    ## Purgin all references to Un-Staged File(s):
       git reset HEAD;
    ## Purging SRC/TRG_DIRs variable(s):
        unset SRC_DIR; unset TRG_DIR;
        echo "";
        return 0;
      }
    

    Output:

    $ git-export /tmp/rel-1.0.0

    Adding '.empty' files to empty folder(s): ... done.

    Checking-Out Index component(s): ... done.

    Resetting HEAD and Index: ... done.

    Purging Git-Specific component(s): ...

    '/tmp/rel-1.0.0/{.buildpath}' files ... done.'

    '/tmp/rel-1.0.0/{.project}' files ... done.'

    '/tmp/rel-1.0.0/{.gitignore}' files ... done.'

    '/tmp/rel-1.0.0/{.git}' files ... done.'

    '/tmp/rel-1.0.0/{.gitattributes}' files ... done.'

    '/tmp/rel-1.0.0/{*.mno}' files ... done.'

    '/tmp/rel-1.0.0/{*~}' files ... done.'

    '/tmp/rel-1.0.0/{.*~}' files ... done.'

    '/tmp/rel-1.0.0/{*.swp}' files ... done.'

    '/tmp/rel-1.0.0/{*.swo}' files ... done.'

    '/tmp/rel-1.0.0/{.DS_Store}' files ... done.'

    '/tmp/rel-1.0.0/{.settings}' files ... done.'

    '/tmp/rel-1.0.0/{.empty}' files ... done.'

    done.

    Archiving Checked-Out component(s): ... done.

    -rw-r--r-- 1 admin wheel 25445901 3 Nov 12:57 /tmp/rel-1.0.0.tgz

    I have now incorporated the 'git archive' functionality into a single process that makes use of 'create_empty' function and other features.

    function git-archive () {
        PREFIX="${1}"; ## sudo mkdir -p ${PREFIX}
        REPO_PATH="`echo "${2}"|awk -F: '{print $1}'`";
        RELEASE="`echo "${2}"|awk -F: '{print $2}'`";
        USER_PATH="${PWD}";
    echo "$PREFIX $REPO_PATH $RELEASE $USER_PATH";
    ## Dynamically added '.empty' files to the Git-Structure:
        cd "${REPO_PATH}"; populate_empty .; echo -en "\n";
    #    git archive --prefix=git-1.4.0/ -o git-1.4.0.tar.gz v1.4.0
    # e.g.: git-archive /var/www/htdocs /repos/domain.name/website:rel-1.0.0 --explode
        OUTPUT_FILE="${USER_PATH}/${RELEASE}.tar.gz";
        git archive --verbose --prefix=${PREFIX}/ -o ${OUTPUT_FILE} ${RELEASE}
        cd "${USER_PATH}";
        if [[ "${3}" =~ [--explode] ]]; then
          if [ -d "./${RELEASE}" ]; then /bin/rm -rf "./${RELEASE}"; fi
          mkdir -p ./${RELEASE}; tar -xzf "${OUTPUT_FILE}" -C ./${RELEASE}
        fi
    ## Purging SRC/TRG_DIRs variable(s):
        unset PREFIX REPO_PATH RELEASE USER_PATH OUTPUT_FILE;
        return 0;
      }
    

提交回复
热议问题