Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite only non-master branches #39

Closed
igitur opened this issue Jan 2, 2020 · 5 comments
Closed

Rewrite only non-master branches #39

igitur opened this issue Jan 2, 2020 · 5 comments

Comments

@igitur
Copy link

igitur commented Jan 2, 2020

Hi,

I'm busy with a SVN to GIT migration of a large repo. My current trunk branch on the SVN repo is located in /trunk/src/ and my branches are in e.g. /branches/branch-name/.

In the new git repo, I would like to keep the ./src directory and have all the code in there. After the git svn migration (using standard tools) the master branch's files end up correctly in ./src, but the branches' files end up in ./, so I would like to rewrite their history to move them into ./src.

I started by playing with git filter-branch, but, as you know, that is incredibly slow.

I tried this tool (thanks!), but it seems these operations are done on a repo level, not specific to branches.

Am I able to rewrite only non-master branches' history?

@newren
Copy link
Owner

newren commented Jan 3, 2020

There are three different ways I can think of to handle this:

  1. Assuming you ran something like this:

    git clone file:///PATH/TO/MIGRATED/REPO MYREPO
    cd MYREPO
    git filter-repo ...

and the git filter-repo modified all branches (despite the fact that you didn't want it to touch master), you could then restore the original master branch like so:

git checkout OTHER_BRANCH
git fetch origin +refs/heads/master:refs/heads/master

  1. You could operate on all refs, but specify the filter such that it does nothing when the tree is already correct. For example,

git filter-repo --commit-callback '
if any(change.filename.startswith(b"src/") for change in commit.file_changes):
return
for change in commit.file_changes:
change.filename = b"src/" + change.filename
'

  1. You could specify the specific refs you want to run by just listing all the refs you do want to edit after the --refs flag. This could look something like:

git filter-repo --refs $(git for-each-ref --format='%(refname)' | grep -v refs/heads/master)

However, the --refs flag also turns off a number of other things you may expect, such as renaming remote tracking branches into normal branches, deleting the old history afterwards, etc. because it doesn't want to delete anything meaningful that you didn't explicitly choose to rewrite and there could be lots of overlap between a branch you didn't overwrite and one you did.

My preference if I were doing this would be roughly (1) then (2) then (3). Hope that helps you get started.

@newren
Copy link
Owner

newren commented Jan 9, 2020

I'll go ahead and close assuming this answered your question, but let me know if that's a bad assumption.

@newren newren closed this as completed Jan 9, 2020
@igitur
Copy link
Author

igitur commented Jan 10, 2020

Sorry, I'm slow. I haven't looked at this further. Promise I'll come back with my findings after I attempt them. Appreciate your help with this a lot, though.

@igitur
Copy link
Author

igitur commented Jan 22, 2020

So, again, sorry for the slow response, but I succeeded, with your suggestions. Option 1 didn't really work as the master branch was still touched.

Option 2 ( and I assume you actually meant git filter-repo and not git filter-branch?) worked perfectly. However, commit hashes changed for the entire histories of the branches, so it took some work for me to rebase the branches on master. But in the end I ended up with all my code in a ./src subdirectory for all branches.

Thanks for all your help. How can I buy you a coffee?

@newren
Copy link
Owner

newren commented Jan 22, 2020

Awesome, glad it worked out for you. Yes, I meant filter-repo and not filter-branch; I edited the comment to correct it. And yeah, changing commit hashes is expected when you're modifying commits; the hashes are a hash of the contents so if the contents change, then the hash has to change. I suspect you meant that there were some old commits that you didn't want the changes applied to, so you just rebased the newer commits on top of some old base.

Anyway, glad it all worked. I don't drink coffee (even being near it can sometimes give me a headache), but people saying thanks for the tool is much appreciated. :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants