Jul 02, 2018

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).

gord

Jul 02, 2018
setup a new remote the normal way (likte a new repository if you use github or whatever)
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

dos

Jul 02, 2018
It's not that hard, you should be able to do it even without any filter-branch magic :) What you need is an interactive rebase for all commits reachable on the branch I: "git rebase -i --root". Then you tell it to squash all the commits from A to E and push the resulting branch into a new repository.

Check out https://stackoverflow.com/questions/435646/combine-the-first-two-commits-of-a-git-repository

Zak Phoenix McKracken

Jul 02, 2018
Uhm.
Maybe you may want to do this interactively.
git rebase -i <after-commit-xxx-that-is-E-in-your-case>

onewheelonly

Jul 02, 2018
I'm no git guru, but I think you can probably do this with a shallow clone. e.g.

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.

onewheelonly

Jul 02, 2018
Aha, actually there's this option on git clone too:

--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.

Vincent Bernat

Jul 02, 2018
This will create a new empty branch:

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).

Carlo Valenti

Jul 02, 2018
Just do it.

tn

Jul 03, 2018
You take your commit I, then run

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.

Jon

Jul 03, 2018
The main thing you want to do is squash all commits A-D into one. Then you have one branch with the commit history you care about. You could then simply delete all other branches and turn that branch into master, or push it to another remote etc.

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.

John Wood

Jul 09, 2018
This is easy and quick. No powerful operations needed. Just shallow clone the newer branch (the one containing E-G-H-I) by using the --depth and -b flags when cloning locally into a new folder (or remotely, doesn't matter).
https://stackoverflow.com/questions/21833870/how-do-i-shallow-clone-a-repo-on-a-specific-branch
Here are the rules for commenting.