How do you initialise the current contents of a directory as the state of a git branch?

62 Views Asked by At

I have a branch A and want to make a list of quite significant changes to it. The end result of these changes already exists in directory B, which I would also like to become the new working copy. In essense, I just want to "Make this directory the latest working copy of my branch."

There are 2 possibilities I am currently aware of to achieve this:

  1. Checkout A into a temporary directory C, delete everything except ".git", copy the contents of directory B into C and then add/commit/push from directory C. Finally, move the entire contents of C back into B.
  2. Clone the repository without checkout into temporary directory C, move the ".git" directory from C into B. Add/commit/push from within B.

The problems with both of these solutions, besides being horribly clunky, is that they require disk space for both directories B and C. Option 1 also involves a little more file shuffling. So currently my best solution to this is option 2, detailed steps given below.

I imagine there's a better way to do this using "reset" or "symbolic-ref". I have tried various options without success.

mkdir /tmp/git_output
cd /tmp/git_output
git init
git remote add origin /path_or_url_to/git/repo.git
git fetch
git checkout name_of_branch
mv .git /path/to/new/src/
cd /path/to/new/src/
git commit -a
git push
rm -rf /tmp/git_output

Thanks for any help.

2

There are 2 best solutions below

2
knittl On

I think it should be possible to delete everything from your working copy (make triple sure to NOT delete your .git folder – make backups!). Then, copy over the contents of your directory B, git add -u (depending on your versoin of Git) to remove missing files from the index and add new files to the index. Commit. Be happy.


Another way I can think of is to initialize a fresh Git repository in your directory B, commit all files, then push to A: cd B; git init; git add .; git commit -m 'complete rewrite'; git push /path/to/A HEAD:rewrite.

Now, in A, create a graft, telling Git that the tip of branch rewrite has the tip of branch master of A as its parent. Then run git filter-branch to make that graft permanent.

0
jthill On
git checkout A
GIT_WORK_TREE=path/to/B git add -An .   # take out the `n` to actually do it
git commit
git checkout as-you-were

(edit: If you're already on branch A you'll need to do a git reset --hard after to refresh your real worktree. )

You can do this without the checkout if you want to get a bit more lowlevel about it:

(
  export GIT_INDEX_FILE=.git/sideband-index
  export GIT_WORK_TREE=path/to/B
  cp .git/HEAD{,~}
  git symbolic-ref HEAD refs/heads/A
  git add -A .
  git commit
  mv .git/HEAD{~,}
)

Or even

(
  export GIT_INDEX_FILE=`mktemp -u`
  export GIT_WORK_TREE=path/to/B
  git add -A .
  git update-ref A $(git commit-tree -m 'hi there!' -p A $(git write-tree))
)