简体   繁体   中英

git rebase a floating branch

I have imported another repo as a branch based on solutions here .

Now, the new imported branch is floated while it should be connect the way specified in the image.

How should I do the rebase?

git checkout imported-branch
git rebase ????? --onto ????

git rebase

You can't get what you've drawn, because you drew in commit hash IDs: f8114a for instance. Given that f8114a is drawn as a root commit, this means that f8114a is always a root commit, in the past, present, and forever in the future too. But in the right hand side of the drawing, f8114a is not a root commit: it has a parent d0ece . So you've claimed that f8114a is both a root commit (no parents) and a regular everyday commit (one parent, d0ece ), and this is simply not possible.

You may be able to get what you want . This depends on precisely what it is that you do want. Trying to do this with git rebase is usually a bad idea, though: if there are any branch-and-merge operations in the set of commits you're trying to graft onto one of your branches, rebase itself will have to re-perform any of the merges involved, and that's a recipe for breaking stuff.

Now, remember that any commit, whatever its hash ID might be, and whatever parent hash IDs it might have, represents a full and complete snapshot of the files that are contained inside that commit. So commit f8114a is a snapshot. Since it it has no parent (on the left side), Git will show it as a comparison against a pseudo-commit that has no files. 1 So f8114a consists of add all of its files , when viewed as a set of changes.

If you take f8114a and copy it to a new-and-¿improved? commit—let's call this f9114a , although the actual hash ID will probably be different, but we need to have something to call it 2 —that does have a parent commit, though, now git show and other Git operations that compare the copy against its parent will have a snapshot to compare against. So now, instead of add all of these files , the diff may say delete most of the files, and create these mostly new ones instead, then change a whole lot of a few remaining files .

If that's OK with you, it's easy to get this to happen in your own repository, without having it happen in any clones anyone makes of your repository. Just use git replace with the --graft option. See the git replace documentation for details.

Once you're satisfied with some replacement(s), you can use a no-op git filter-repo (or the old but still supported, and included with Git distributions, git filter-branch ) to rewrite commits reachable from the tip of imported-branch . This will "cement the replacement in place" and allow you to discard the graft; cloning this filtered repository will produce a copy of the filtered repository, which no longer uses the replacement trick.


1 Technically Git uses the empty tree to fake up this pseudo-commit. It diffs your commit's tree against the empty tree to produce all the "add entire file" diff-hunks.

2 Call it Fred or Barney or Wilma if you like; just don't call it late for dinner.

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