Question

I have a Git repository with dozens of commits. I want the last commit to be the only commit - meaning the repository would behave as if it was just initialized and the current file state is the only commit.

Is there a better way to do it than creating a new repo?

Was it helpful?

Solution

Use the following:

$ git checkout --orphan new-master master
$ git commit -m "Initial commit for new root"

# Compare new-master with master to double-check that
# their final commit states are identical:
$ git diff new-master master

# If there is no diff/patch output, then they're identical,
# so it's safe to delete master:
$ git branch -D master
$ git branch --move new-master master

The --orphan flag creates an entirely separate commit tree, with a different root commit. It follows basic branching syntax, so the arguments that follow are the name for the new branch, followed by the starting point, which can be any Git revision specification, including a commit sha or a branch name.

So in the first command, you tell Git to make a new orphan branch starting with the same state as the current state of the master branch. Then you need to commit the new root, just as you would have done the first time with your original root.

Next you want to make sure that the final state of new-master really is identical to the final commit state of master, so do a diff of them to make sure (no diff output means they are identical). Then to cleanup, you delete the old master branch and rename the new branch to it.

Here's the explanation of the --orphan flag from the official Linux Kernel Git documenation for git-checkout(1) (with missing syntax correction by me on the first line):

--orphan <new_branch> [<start_point>]

Create a new orphan branch, named <new_branch>, started from <start_point> and switch to it. The first commit made on this new branch will have no parents and it will be the root of a new history totally disconnected from all the other branches and commits.

The index and the working tree are adjusted as if you had previously run git checkout <start_point>. This allows you to start a new history that records a set of paths similar to <start_point> by easily running git commit -a to make the root commit.

This can be useful when you want to publish the tree from a commit without exposing its full history. You might want to do this to publish an open source branch of a project whose current tree is "clean", but whose full history contains proprietary or otherwise encumbered bits of code.

If you want to start a disconnected history that records a set of paths that is totally different from the one of <start_point>, then you should clear the index and the working tree right after creating the orphan branch by running "git rm -rf ." from the top level of the working tree. Afterwards you will be ready to prepare your new files, repopulating the working tree, by copying them from elsewhere, extracting a tarball, etc.

OTHER TIPS

If you don't need to preserve the repo configuration, it's easiest to just do

rm -rf .git/
git init .

Even then I think just backing up ~/.git/config and ~/.git/info/exclude should be sufficient.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top