Jump to content

User:Randomguy3: Difference between revisions

From KDE Community Wiki
Randomguy3 (talk | contribs)
Randomguy3 (talk | contribs)
Line 17: Line 17:
== Filtering ==
== Filtering ==


See [http://whileimautomaton.net/2010/04/03012432 mastering git filter-branch: points to extract a subproject] for helpful hints.
Usually, you do not want to include a git repository wholesale in another repository. More often, you want to include only some files. You probably also want to alter the commit messages to disable the KDE commit hook keywords, so that the merged history does not cause CCMAILs to be sent for ancient commits. <tt>git filter-branch</tt> can do all of this and more.


If you want to trim the history first (which will change the commit identities), you can do something like
A combination of <tt>--tree-filter</tt>, <tt>--prune-empty</tt> and <tt>--msg-filter</tt> generally gets what you want. For example,


  git filter-branch --prune-empty --tree-filter "find -type f -\! -path './.git/*' -\! -name foo.\* -delete" HEAD
  git filter-branch --prune-empty \
                  --tree-filter "find -type f -\! -path './.git/*' -\! -name foo.\* -delete" \
                  --msg-filter 'sed -e 's/^\(CCMAIL\|REVIEW\|BUG\|CCBUG\|FEATURE\)/(&)/'; echo; echo "Commit $GIT_COMMIT in <source-repo>"' \
                  HEAD


This example will remove everything that does not match <tt>foo.*</tt>. Note the <tt>-path</tt> argument to <tt>find</tt> that makes sure you don't delete any of git's own files. <tt>--prune-empty</tt> will remove non-merge commits that no longer have any effect on the tree.
This example will remove everything that does not match <tt>foo.*</tt>. Note the <tt>-path</tt> argument to <tt>find</tt> that makes sure you don't delete any of git's own files. <tt>--prune-empty</tt> will remove non-merge commits that no longer have any effect on the tree (you can run <tt>git rebase</tt> after to trim the merge commits if you want). <tt>--msg-filter</tt> neuters the keywords and adds information about where the commit came from (don't forget to change <tt>&lt;source-repo&gt;</tt>!


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 <tt>--msg-filter</tt>). When I wanted to just grab the commits relevant to the two <tt>FindDocBook*.cmake</tt> files in extra-cmake-modules (which had faked history from kdelibs), I did
More complex filters are possible. Have a look at the man page for <tt>git-filter-branch</tt>.


git filter-branch \
See [http://whileimautomaton.net/2010/04/03012432 mastering git filter-branch: points to extract a subproject] for more helpful hints.
  --tree-filter "find -type f -\! -path './.git/*' -\! -name FindDocBook\*.cmake -delete" \
  --msg-filter 'sed -e "/^CCMAIL/d" -e "/^REVIEW/d"; echo; echo "Commit $GIT_COMMIT in extra-cmake-modules"' \
  --prune-empty \
  HEAD
 
This left some useless merge commits, which I eliminated with
 
git filter-branch --parent-filter "sed -e 's/-p 755debcea57d6ddab0cf851117fb00f3ab39af6f//' -e 's/-p 91d8128e5fc3f20a4621e2f2516ddd34b979bf01//'" --prune-empty -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.

Revision as of 23:52, 25 April 2014

Git Magic

Safety Precautions

Always work on a disposable copy of the repo with all the remotes removed, so if you screw up, it doesn't really matter. Also, work on a separate branch. That way, you can use git reset --hard <original-branch> to get back to the starting state.

Also, make sure there are no grafts around (eg: linking to the old kdelibs history in the case of frameworks). The safest way to do this is to use fresh checkouts.

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.

Create a commit in the source repo that removes any files you don't want to copy, and rearranges the remaining files to be as you want them to appear in the target repo. Then go to the root of the target repository and use git-merge-repo (from the kde-dev-scripts repository) to merge in the source repo:

/path/to/kde-dev-scripts/git-merge-repo <path to source repo>

Filtering

Usually, you do not want to include a git repository wholesale in another repository. More often, you want to include only some files. You probably also want to alter the commit messages to disable the KDE commit hook keywords, so that the merged history does not cause CCMAILs to be sent for ancient commits. git filter-branch can do all of this and more.

A combination of --tree-filter, --prune-empty and --msg-filter generally gets what you want. For example,

git filter-branch --prune-empty \
                  --tree-filter "find -type f -\! -path './.git/*' -\! -name foo.\* -delete" \
                  --msg-filter 'sed -e 's/^\(CCMAIL\|REVIEW\|BUG\|CCBUG\|FEATURE\)/(&)/'; echo; echo "Commit $GIT_COMMIT in <source-repo>"' \
                  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 (you can run git rebase after to trim the merge commits if you want). --msg-filter neuters the keywords and adds information about where the commit came from (don't forget to change <source-repo>!

More complex filters are possible. Have a look at the man page for git-filter-branch.

See mastering git filter-branch: points to extract a subproject for more helpful hints.