1

I have a private git repository in which I track a personal project. I also have copies of this project from before I used source control. I would like to add those copies to the history of this repository. Since only I have access to the repository, I should be able to rewrite history without the usual problems.

What is the best way to do this? Should I create a new, blank project and successively add old projects and then replay the current repository onto it, or is there an alternate approach? If I do, will this cause problems with the remote repo (I'm using bitbucket)?

Charles
  • 11,269
  • 13
  • 67
  • 105
  • Rewriting history will cause problems for the remote inasmuch as it requires a forced push and others will not be able to fast forward pull. As long as you're ok with that, then there are lots of ways to accomplish what you're trying to do. The best will depend on the circumstances I think. – Jeff Puckett Jul 06 '16 at 00:23
  • @JeffPuckettII: Yes I'm ok with that -- there are no others, only I have access. – Charles Jul 06 '16 at 02:30

1 Answers1

2

"Should I create a new, blank project and successively add old projects and then replay the current repository onto it?"

Yes.

Assuming the "pre-history" merges cleanly onto the existing history you can graft the two histories together with two git commands. From within your new git repository, run this:

git --git-dir=/path/to/original/.git log -m -p --reverse --first-parent --binary --pretty=email | git am --keep-non-patch --whitespace=fix

That's kind of hard to see, so here it is formatted weirdly but visibly (and still runnable as long as you copy & paste all-in-one):

git --git-dir=/path/to/original/.git \
  log -m -p --reverse --first-parent --binary --pretty=email |
git am --keep-non-patch --whitespace=fix

Run a "git log" command afterwards to make sure everything is correct. Once you are happy, I recommend deleting or renaming the existing bitbucket repo, and pushing this one in its place.

Caveat #1: "git log --first-parent" strips out all branches and merges from the history, and so the result is just a single linear sequence of commits. (For more reading about --first-parent: GIT: How can I prevent foxtrot merges in my 'master' branch?, and https://bit-booster.blogspot.ca/2016/02/no-foxtrots-allowed.html).

Caveat #2: "git am" hates empty commits (e.g., git commit --allow-empty), and so if you have any of those, you will have to break the procedure into a three step process: 1. git log > git_am.log. 2. Remove empty patches from "git_am.log". 3. cat git_am.log | git am

Here are some notes about the "git log" options used above:

-m
   Include patches caused by merge commits.

-p
   Show patches in the "git log" output.

--reverse
   Reverse "git log" ordering (since we want oldest-to-newest).

--first-parent
   Only include 1st parent of merge commits.

--binary
   Include binary-diffs in output.

--pretty=email
   Have "git log" output its data in the "email" format
   that "git am" is expecting.

I leave looking up the "git am" options as an exercise for the reader (e.g., "git help am").

Community
  • 1
  • 1
G. Sylvie Davies
  • 5,049
  • 3
  • 21
  • 30