9

I have used "git replace" to substitute a branch (with no common ancestor) 22b2b25 for a commit in master. I want this change to be permanent. I'm not interested in the previous history. In the output below the top five commits are from the original master branch and the bottom 2 come from a different branch.

When I pushed this to a new repository the git-replace was lost and the old history reappeared. Is there a way to make this change permanent?

branch master looks like the below in the original repo. I want to see this in the remote repo and subsequent clones.

[mike@localhost canal_site]$ git log --oneline --decorate
cdf0ae3 (HEAD, origin/master, master) MM: sqlencode course name for ad-hoc courses
2b57df5 MM: fixes for changes so far
7916eaf MM: ad hoc - more refactoring
1e00d22 MM: reformatted code
e36cee1 factored out equal ops
22b2b25 (origin/prod20140313, prod20140313) initial load from production 9-June-2015
08379cd initial inclusion of production files from 9-June-2015
Mat
  • 202,337
  • 40
  • 393
  • 406
mikemay
  • 3,707
  • 6
  • 34
  • 35
  • @Mat Thanks for the reformatting and up vote. I rather thought it was the use of the code stuff for non-code that had upset somebody but a -1 kills your question. – mikemay Jul 11 '15 at 13:55

1 Answers1

12

git replace alone isn't enough: replacing one commit isn't enough.

The next commit must now reference the replaced commit as a parent.

As mentioned in "Removing a whole bunch of commits from git":

Backup your repo via git clone.
Find out the first commit you do like after the commits you do not like and remember the hash of its direct ancestor (in the following bbb).
Then find the first commit you do like before the commits you do not like (in the following aaa):

git replace bbb aaa

Take a look at your repository (with git log) and check whether everything is as it should be after your intended change.
But the replace command just adds some meta information into .git/refs/replace, which git commands interpret correspondingly.
In order to make these changes permanent, you may use git filter-branch:

git filter-branch -- --all

Then you would need to force push (git push --force) in order to override the remote repo with the new history of the branch. Or you van just push to a new empty bare repo.


Update (inspired from Stephen's comment)

As I noted in Oct. 2019 in "Git commands that could break/rewrite the history", git filter-branch or BFG are obsolete.
git filter-repo is easier to use and more efficient.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 1
    `git-filter-branch` is outdated now, and the documentation suggests using `git filter-repo` https://git-scm.com/docs/git-filter-branch `git filter-repo --force` worked for me. – Stephen Jun 15 '20 at 14:07
  • @Stephen Thank you. I have updated this old answer accordingly. I did notice `git filter-repo` in my 2019 answer https://stackoverflow.com/a/58251653/6309. – VonC Jun 15 '20 at 14:31