简体   繁体   中英

How to move part of git branch to different repo?

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

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.

update:

Base on the comments and our discussion, it seems you will maybe face some conflicts.

As well said @mat :

"but it ended up in merge conflicts" Why did it end? Merge conflicts only end things if you stop when you get them. Don't. The correct response to merge conflicts is to resolve them. Remember, merge conflicts are not bad. They are not an error condition. They are not a problem. They merely indicate that what's happened is beyond Git's capacity to perform automatic merge. Merge conflicts are a good thing: they greatly reduce the chances that Git will do something wrong while merging for you.

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:

  1. Create a new branch from F :

    $ git checkout -b newbranch f78ffc7

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

  3. Cherry-pick commits G and H from master :

    $ 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM