Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>What you want is <code>git filter-branch</code>, which can move a whole repository into a subtree, preserving history by making it look as if it's always been that way. Back up your repository before using this!</p> <p>Here's the magic. In <code>/foo/bar</code>, run:</p> <pre><code>git filter-branch --commit-filter ' TREE="$1"; shift; SUBTREE=`echo -e 040000 tree $TREE"\tbar" | git mktree` git commit-tree $SUBTREE "$@"' -- --all </code></pre> <p>That will make the <code>/foo/bar</code> repository have another 'bar' subdirectory with all its contents throughout its whole history. Then you can move the entire repo up to the <code>foo</code> level and add <code>baz</code> code to it.</p> <p><em>Update</em>:</p> <p>Okay, here's what's going on. A commit is a link to a "tree" (think of it as a SHA representing a whole filesystem subdirectory's contents) plus some "parent" SHA's and some metadata link author/message/etc. The <code>git commit-tree</code> command is the low-level bit that wraps all this together. The parameter to <code>--commit-filter</code> gets treated as a shell function and run in place of <code>git commit-tree</code> during the filter process, and has to act like it.</p> <p>What I'm doing is taking the first parameter, the original tree to commit, and building a new "tree object" that says it's in a subfolder via <code>git mktree</code>, another low-level git command. To do that, I have to pipe into it something that looks like a git tree i.e. a set of (mode SP type SP SHA TAB filename) lines; thus the echo command. The output of <code>mktree</code> is then substituted for the first parameter when I chain to the real <code>commit-tree</code>; <code>"$@"</code> is a way to pass all the other parameters intact, having stripped the first off with <code>shift</code>. See <code>git help mktree</code> and <code>git help commit-tree</code> for info.</p> <p>So, if you need multiple levels, you have to nest a few extra levels of tree objects (this isn't tested but is the general idea):</p> <pre><code>git filter-branch --commit-filter ' TREE="$1" shift SUBTREE1=`echo -e 040000 tree $TREE"\tbar" | git mktree` SUBTREE2=`echo -e 040000 tree $SUBTREE1"\tb" | git mktree` SUBTREE3=`echo -e 040000 tree $SUBTREE2"\ta" | git mktree` git commit-tree $SUBTREE3 "$@"' -- --all </code></pre> <p>That should shift the real contents down into <code>a/b/bar</code> (note the reversed order).</p> <p><strong>Update</strong>: Integrated improvements From Matthew Alpert's answer below. Without <code>-- --all</code> this only works on the currently-checked out branch, but since the question is asking about a whole repo, it makes more sense to do it this way than branch-by-branch.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload