Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

git - getting ALL previous version of a specific file/folder

I want to retrieve all previous version of a specific file in a git repository.

I see it is possible to get one specific version with the checkout command, but I want them all. And the git clone command with the depth option doesn't seem to allow me to clone subfolder ("not valid repository name").

Do you know if it is possible and how?

Thank you

like image 278
max152 Avatar asked Oct 11 '12 23:10

max152


People also ask

Can you download specific folder GitHub?

Step1: Input github url to the field at the top-right. Step2: Press enter or click download for download zip directly or click search for view the list of sub-folders and files. Step3: Click "Download Zip File" or "Get File" button to get files.

Which command is used to explore the previous versions of a project?

git checkout recovers old versions of files.


1 Answers

OP wanted to retrieve all versions, but the answers would not deliver. Especially if the file has hundreds of revisions (all suggestions are too manual). The only half-working solution was proposed by @Tobias in the comments, but suggested bash loop would build files in random order as well as it generates hundreds of empty files when used against our repos. One of the reasons was that "rev-list --all --objects" would list different objects (trees included - but useless for our purpose).

I started with Tobias's solution, added counters, clean up a bit and end up reinventing the wheel in form of the bash script listed below.

The script would:

  • extract all file versions to /tmp/all_versions_exported
  • take 1 argument - relative path to the file inside git repo
  • give result filenames numeric prefix (sortable)
  • mention inspected filename in result files (to tell apples apart from oranges:)
  • mention commit date in the result filename (see output example below)
  • not create empty result files

cat /usr/local/bin/git_export_all_file_versions

#!/bin/bash  # we'll write all git versions of the file to this folder: EXPORT_TO=/tmp/all_versions_exported  # take relative path to the file to inspect GIT_PATH_TO_FILE=$1  # ---------------- don't edit below this line --------------  USAGE="Please cd to the root of your git proj and specify path to file you with to inspect (example: $0 some/path/to/file)"  # check if got argument if [ "${GIT_PATH_TO_FILE}" == "" ]; then     echo "error: no arguments given. ${USAGE}" >&2     exit 1 fi  # check if file exist if [ ! -f ${GIT_PATH_TO_FILE} ]; then     echo "error: File '${GIT_PATH_TO_FILE}' does not exist. ${USAGE}" >&2     exit 1 fi  # extract just a filename from given relative path (will be used in result file names) GIT_SHORT_FILENAME=$(basename $GIT_PATH_TO_FILE)  # create folder to store all revisions of the file if [ ! -d ${EXPORT_TO} ]; then     echo "creating folder: ${EXPORT_TO}"     mkdir ${EXPORT_TO} fi  ## uncomment next line to clear export folder each time you run script #rm ${EXPORT_TO}/*  # reset coutner COUNT=0  # iterate all revisions git rev-list --all --objects -- ${GIT_PATH_TO_FILE} | \     cut -d ' ' -f1 | \ while read h; do \      COUNT=$((COUNT + 1)); \      COUNT_PRETTY=$(printf "%04d" $COUNT); \      COMMIT_DATE=`git show $h | head -3 | grep 'Date:' | awk '{print $4"-"$3"-"$6}'`; \      if [ "${COMMIT_DATE}" != "" ]; then \          git cat-file -p ${h}:${GIT_PATH_TO_FILE} > ${EXPORT_TO}/${COUNT_PRETTY}.${COMMIT_DATE}.${h}.${GIT_SHORT_FILENAME};\      fi;\ done      # return success code echo "result stored to ${EXPORT_TO}" exit 0 

Usage example:
cd /home/myname/my-git-repo  git_export_all_file_versions docs/howto/readme.txt     result stored to /tmp/all_versions_exported  ls /tmp/all_versions_exported     0001.17-Oct-2016.ee0a1880ab815fd8f67bc4299780fc0b34f27b30.readme.txt     0002.3-Oct-2016.d305158b94bedabb758ff1bb5e1ad74ed7ccd2c3.readme.txt     0003.29-Sep-2016.7414a3de62529bfdd3cb1dd20ebc1a977793102f.readme.txt     0004.28-Sep-2016.604cc0a34ec689606f7d3b2b5bbced1eece7483d.readme.txt     0005.28-Sep-2016.198043c219c81d776c6d8a20e4f36bd6d8a57825.readme.txt     0006.9-Sep-2016.5aea5191d4b86aec416b031cb84c2b78603a8b0f.readme.txt     <and so on and on . . .> 

edit: if you see errors like this:

fatal: Not a valid object name 3e93eba38b31b8b81905ceaa95eb47bbaed46494:readme.txt

it means you've started the script not from the root folder of your git project.

like image 134
Dmitry Shevkoplyas Avatar answered Sep 21 '22 07:09

Dmitry Shevkoplyas