{"thread":{"id":"16732","subject":"git-svn and \"svn move\" of an entire project","startedAt":"2008-12-14T23:14:37Z","lastAt":"2008-12-14T23:14:37Z","messageCount":1,"participants":["Jukka Zitting"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"97897","messageId":"510143ac0812141514k28f6dcd4y57bc50600205cd7c@mail.gmail.com","threadId":"16732","inReplyTo":null,"subject":"git-svn and \"svn move\" of an entire project","fromName":"Jukka Zitting","fromEmail":"jukka.zitting@gmail.com","sentAt":"2008-12-14T23:14:37Z","receivedAt":"2008-12-14T23:14:37Z","isPatch":false,"sender":{"key":"jukka.zitting@gmail.com","avatar":null},"body":"Hi,\n\nI'm hosting git-svn mirrors of many Apache projects [1] and every now\nand then I need to deal with cases where an entire project (trunk,\ntags, branches, everything) is moved from one location to another\nwithin the svn server. For example in revision 723328 [2] the Apache\nAbdera project was moved from incubator/abdera to just abdera.\n\nAt [3] I found instructions on how to cope with such situations when\ngit-svn is used to follow only the svn trunk of a project. Based on\nthat I came up with the bash script below that allows me to update a\nfull (init -s) git-svn mirror to point to a new location in svn.\n\nThe script seems to work fine but I'm wondering if there's an easier\nway to achieve this (and if there are any obvious mistakes in my\nscript). One alternative is of course to recreate the full git-svn\nmirror, but that risks breaking the git history if someone has\nmeanwhile modified a commit message in svn or changed an author name.\n\nIdeally I'd just run \"git svn init\" again with the new location and\nlet git-svn take care of the rest. Unfortunately that doesn't seem to\nwork and I'm not familiar enough with git-svn internals to know where\nto start implementing something like this.\n\n[1] http://jukka.zitting.name/git/\n[2] http://svn.apache.org/viewvc?view=rev&revision=723328\n[3] http://duncan.mac-vicar.com/blog/archives/282\n\nBR,\n\nJukka Zitting\n\n----\n\n#!/bin/bash\n\n# Location of the authors file\nAUTHORS=/home/jukka/git/authors.txt\n\n# Example:\n# move-svn-project.sh /var/git/abdera.git 723328 incubator/abdera abdera\nDIR=$1\nREV=$2\nOLD=$3\nNEW=$4\n\n# Set GIT_DIR so all git commands know which repo to use\nexport GIT_DIR=$DIR\n\n# This function is the main workhorse of this script.\n# It takes an existing git-svn branch and updates it\n# to point to the first corresponding post-move revision\n# in svn. If the branch no longer exists in svn, it is\n# removed from here as well.\nmap() {\n  REF=$1\n  URL=$2\n  echo \"Mapping $REF to $URL\"\n\n  # Keep a backup copy of the original git-svn metadata\n  cp \"$GIT_DIR/svn/.metadata\" \"$GIT_DIR/svn/.metadata.bak\"\n\n  # Set up a temporary git-svn remote for just this subtree\n  git svn init -R tmp -i tmp-git-svn-map-branch \"$URL\"\n\n  # Get the first post-move version of this subtree and modify the branch\n  git svn fetch -r \"$REV\" --authors-file \"$AUTHORS\" tmp\n  if git rev-parse --verify --quiet refs/remotes/tmp-git-svn-map-branch; then\n    git update-ref \"$REF\" refs/remotes/tmp-git-svn-map-branch\n  else\n    git update-ref -d \"$REF\"\n  fi\n\n  # Remove all the temporary git-svn settings\n  git update-ref -d refs/remotes/tmp-git-svn-map-branch\n  git config --remove-section svn-remote.tmp\n  rm -rf $GIT_DIR/svn/tmp-git-svn-map-branch\n  mv $GIT_DIR/svn/.metadata.bak $GIT_DIR/svn/.metadata\n}\n\n# Map all git-svn branches to corresponding new URLs\nBASE=$(git config svn-remote.svn.url)\ngit for-each-ref refs/remotes | cut -d / -f 3- | while read REF; do\n  case \"$REF\" in\n  *@*)\n    echo \"Skipping $REF\"\n    ;;\n  trunk)\n    map \"refs/remotes/trunk\" \"$BASE/$NEW/trunk\"\n    ;;\n  tags/*)\n    map \"refs/remotes/$REF\" \"$BASE/$NEW/$REF\"\n    ;;\n  *)\n    map \"refs/remotes/$REF\" \"$BASE/$NEW/branches/$REF\"\n    ;;\n  esac\ndone\n\n# Update git-svn configuration to point to the new URLs\nfor NAME in fetch branches tags; do\n  VALUE=\"$(git config svn-remote.svn.$NAME)\"\n  git config \"svn-remote.svn.$NAME\" \"${VALUE/#$OLD/$NEW}\"\ndone\n\n# Clean the old git-svn directory, it'll be regenerated on next update\nrm -r \"$GIT_DIR/svn\"\n"}]}