Let assume that i have a git repo with commits:
H - add stuff
G - add stuff
F - add stuff
E - remove big files
D - add stuff
C - add big files
B - add stuff
A - initial commit
I want to move this branch which is master to different repo from commit F to H without the stuff from A to E. Basically the new repo would contain squashed commits from A to E plus commits F,G and H.
Update: Based on comments i tried the following, but it ended up in merge conflicts:
git checkout A
git checkout -b cleanup
git checkout master
git rebase -i cleanup
pick A
squash B
squash C
squash D
squash E
pick F
pick G
pick H
CodePudding user response:
Git internally is just a folder that contains objects that represent snapshots of the state of your files.
So the first step in the process is to copy your entire project including the .git
folder (this is crucial you may not see it if it hidden, but it will be okay if you just copy the all project folder).
The next step is to operate the git rebase
command in the copied folder like this:
git rebase -i <A hash in this exmple ce0e2fd>
You'll be presented with an interactive window like this:
ce0e2fd pick A initial commit
72ab3c4 pick B add stuff
8150939 pick C add big files
301c1e1 pick D add stuff
ab123c4 pick E remove big files
342d191 pick F add stuff
12ce3d7 pick G add stuff
23fd457 pick H add stuff
...
If you're using the default vim editor, you may need to learn how to use it, too.
My recommendation is to use vscode, use this tutorial to change it to your default editor.
Interactive rebase provides instructions for your scenario, so you should change "pick"
to "squash"
for A till E:
ce0e2fd squash A initial commit
72ab3c4 squash B add stuff
8150939 squash C add big files
301c1e1 squash D add stuff
ab123c4 squash E remove big files
342d191 pick F add stuff
12ce3d7 pick G add stuff
23fd457 pick H add stuff
This will squash A till E into a single commit, allowing you to change the commit message.
If you're happy to use the commit message of A, you can use "fixup"
instead of "squash"
and you won't be prompted to update the commit message.
In case you want to make sure that the commits A to E are completely removed and no longer accessible, please check this answer on how to prune dangling commits.
CodePudding user response:
This is pretty straightforward. Assuming the following history:
4103511 (HEAD -> master) H - add stuff
7946283 G - add stuff
f78ffc7 F - add stuff
ced1bdc E - remove big files
1234ee9 D - add stuff
b9fd6c6 C - add big files
af5a768 B - add stuff
a1436d0 A - Initial commit
then you can:
Create a new branch from
F
:$ git checkout -b newbranch f78ffc7
Squash all commits into one on
newbranch
(thanks to this answer for the tip):$ git reset $(git commit-tree HEAD^{tree} -m "F - add stuff")
Cherry-pick commits
G
andH
frommaster
:$ git cherry-pick 7946283
$ git cherry-pick 4103511
you'll end up with a new branch newbranch
which contains the desired history:
1fafbe7 (HEAD -> newbranch) H - add stuff
4e9d879 G - add stuff
7bc7b56 F - add stuff