User:Randomguy3: Difference between revisions
Randomguy3 (talk | contribs) Created page with "= Git Magic = == Merging in complete history == Used this for moving files from kapidox to kdoctools. Good when the history of the source repo doesn't contain too much you ..." |
Randomguy3 (talk | contribs) |
||
Line 17: | Line 17: | ||
git commit | git commit | ||
== Filtering == | |||
If you want to trim the history first (which will change the commit identities), you can do something like | If you want to trim the history first (which will change the commit identities), you can do something like |
Revision as of 14:26, 24 February 2014
Git Magic
Merging in complete history
Used this for moving files from kapidox to kdoctools. Good when the history of the source repo doesn't contain too much you won't care about in the target repo. Preserves commit identities.
First, create copies of the repos with no remotes (or scratch remotes), so you can't screw anything up.
Move/delete files in the source repo so that the remaining files are as you want them to appear in the target repo.
git fetch <path to source repo> GIT_INDEX_FILE=.git/tmp-index git-read-tree FETCH_HEAD GIT_INDEX_FILE=.git/tmp-index git-checkout-index -a -u git-update-index --add -- (GIT_INDEX_FILE=.git/tmp-index git-ls-files) cp .git/FETCH_HEAD .git/MERGE_HEAD <edit MERGE_HEAD so it is just the sha sum> git commit
Filtering
If you want to trim the history first (which will change the commit identities), you can do something like
git filter-branch --prune-empty --tree-filter "find -type f -\! -path './.git/*' -\! -name foo.\* -delete" HEAD
This example will remove everything that does not match foo.*. Note the -path argument to find that makes sure you don't delete any of git's own files. --prune-empty will remove non-merge commits that no longer have any effect on the tree.
More complex filters are possible; doing as much as possible in the same filter-branch command is probably a good thing to aim for, especially if you want to record the original commit SHA (using --msg-filter). When I wanted to just grab the commits relevant to the two FindDocBook*.cmake files in extra-cmake-modules (which had faked history from kdelibs), I did
git filter-branch \ --tree-filter "find -type f -\! -path './.git/*' -\! -name FindDocBook\*.cmake -delete" \ --msg-filter 'sed -e "/^CCMAIL/d" -e "/^REVIEW/d"; echo "Derived from commit $GIT_COMMIT in extra-cmake-modules"' \ --prune-empty \ HEAD
followed by
git filter-branch --parent-filter "sed -e 's/-p 837b672bbb36a5f449ac4785f0898997f4b36ac2//' -e 's/-p 559a21763b5915a7e09008d581e27ae2477af7f2//'" -f HEAD
where the two commit SHAs were cut-off points: I didn't want those commits or anything preceding them (because they didn't contain the file I was interested in). These were SHAs after the first filter-branch; the reason I couldn't put them in the first filter-branch appears to be because by the time a commit was reached, its parents had already been rewritten, and so their SHAs had changed.
Do filters on a branch, so you can git reset --hard master if it goes wrong!