Christopher
Christopher

Reputation: 878

Git: How can I put a commit between older commits without changing the files/folders of later commits?

I have a repository with a series of commits. Lets say two old commits are A and directly after it C:

A--C

In commit C I have not checked in a new version of the old files, but in fact completely new files with the same name.

This makes the diff for commit C look messy - in fact this diff does not make sense as the files are completely different anyway.

What I want is to add a commit between A and C (let's call this one B then):

A--B--C

In this commit B I want to remove the files and folders, which I have changed with C.

I know that with the following I can add a new commit between A and C:

git rebase --interactive A^

then doing an "edit" on commit A

and then

git rm -rf file folder/
git commit -m "B" # New commit with name B

How do I now get the same files and folders, which I had after the original commit C, meaning before B was in place?

With other words: How can I get C again, but without the removal I did in B?

Upvotes: 2

Views: 228

Answers (2)

Christopher
Christopher

Reputation: 878

Here are the steps I have done to solve the issue:

git checkout A
git rm -rf file folder/
# Create a new commit with name B on top of A:
git commit -m "B"
# On top of B create a new commit with what was C:
echo 'new C commit' | git commit-tree C^{tree} -p HEAD 

This will create a new C commit and return its SHA hash. At this point, a checkout of the new C commit contains exactly what you would get, if you checked out the original C commit.

git checkout new-C-commit # No, this did not happen with git commit-tree
git rebase --onto HEAD C master

This rebases the branch (in my case it's master), starting with the first commit after the original C commit on the new C commit. This will apply without problems as both commits effectively create the same files and folders.

Upvotes: 0

knittl
knittl

Reputation: 265574

You can use git-commit-tree for that:

git checkout A
git rm -rf file folder/
git commit -m 'B'
echo 'new C commit' | git commit-tree C -p HEAD
# create a new branch/update branch with the commit id printed by commit-tree

This will:

  • Checkout A (detach HEAD)
  • Remove files and folder, create a new commit B
  • Create a new commit with the same set of files/state as the original commit C
  • You will then have to update your old branch to point to the new commit (currently still a detached HEAD)

An alternative way might be to use grafts and then filter-branch to make them permanent:

git checkout A
git rm -rf file folder/
git commit -m B
echo `git rev-parse C` `git rev-parse HEAD` >> .git/info/grafts
git filter-branch A^..C

Upvotes: 1

Related Questions