Git Question
I have a Git question. I kind of know how to do this but in a horrible brut forced way and I'd like to know if there is a "better" or more "elegant" way to do it.
The letters A-I are misleading. The actual repository has around 600 commits (and close to 1000 files/directories).
I have a master branch (A-F) and I created a new branch (G,H,I) and have been actively working on it. The master branch has had a few commits since the branch, but not a lot.
What I'd like to do is create a 2nd repository that only includes E,G,H and I. The old repository is getting huge and the new branch (G,H,I) has become significantly different from the master branch.
Is there a clean way to do this? I assume it involves --rebase, --reset, --hard, --or-your-fucked flags. I really love Git, it's amazingly powerful and equally as confusing.
Given there are hundreds of commits and close to a thousand files and directories, I want something that doesn't involve me having to interact with each commit or rechecking in files. The history from E-I is important to keep (and is way more than 4 commits).
Check out https://stackoverflow.com/questions/435646/combine-the-first-two-commits-of-a-git-repository
Maybe you may want to do this interactively.
git rebase -i <after-commit-xxx-that-is-E-in-your-case>
git clone <repo> --depth X --branch Y
Where Y is the name of the branch with "I" as the HEAD. Your clone should only contain that branch, because --single-branch is implied.
The interesting part will be working out the value of X. It expects a number for the depth, not a commit ID.
--shallow-since=<date>
Create a shallow clone with a history after the specified time.
So that combined with --single-branch and --branch should give you what you want.
git checkout --orphan new
Then, pick all the code from E:
git checkout E -- .
git add .
git commit -m "Initial commit"
Then, add back the remaining commits:
git rebase --onto new E I
If I is a branch and you don't want to loose it, but a tag on it before that (git tag old I). This way, you can still reset it to its old value (git branch -f I old). If everything is correct, you can either delete the old branch (and tag) and prune the repository (git gc --prune=now) or just export the branch to a new repository (git remote add XXXX YYY; git push XXXX new).
git rebase -i --root
in the editor replace every "pick" in front of commits B-E with "squash" (using search/replace of course). This gives you the layout you want.
Alternatively you can just start a new repository with the state of E (i.e., check out E, delete .git, and run git init && git add . && git commit) and then migrate the patches G-I by running
git format-patch E..I
in the old repository and
git am [path-to-patches]0*
in the new one. First strategy squashes all old commits into one, keeping the commit messages, while new second strategy just forgets the past.
Googling around for squashing old commits yields quite a few results. Usually you need the begining and end commits, or know how many you want to squash.
If you squash old commits, and want to push it to the old repository as well, you will have to force push to overwrite history. You can push to a new repository instead and keep the old one.
https://stackoverflow.com/questions/21833870/how-do-i-shallow-clone-a-repo-on-a-specific-branch
then just
> git push <new remote> <current_branch>:master
it'll take the current branch and push it as the master to that new remote