Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Git Repository Join

Combines separate git repositories into a single monolithic git repository, prepending the source repo name to every commit message. It only includes master branches from each repository, but otherwise complete version history is maintained. Mainly just a convenient bash wrapper around git commands.
Combines separate git repositories into a single monolithic git repository, prepending the source repo name to every commit message. It only includes one selectable branch ('master' by default) from each repository, but otherwise complete version history is maintained. Mainly just a convenient bash wrapper around git commands.

## Usage

Expand Down Expand Up @@ -31,9 +31,10 @@ where repo_data.txt is in the format:
repo1 git@github.com:username/repo1.git
newname git@github.com:username/repo2.git
repo3 /path/locally/repo3
repo4 /path/locally/repo3 custom-branch
```

each row is separated by a newline and the name and url are separated by a space character (tabs not supported!).
each row is separated by a newline and contains the name, the url and optionally a branch name separated by a space character (tabs not supported!).

## Expected Result

Expand All @@ -43,23 +44,24 @@ Your new top-level working directory will contain:
repo1
newname
repo3
repo4
```

Where each subfolder contains the HEAD master commit from the corresponding source repository. n.b. old commit ids are lost in this process - so don't count on being able to reference your new repository with old commit ids.
Where each subfolder contains the HEAD commit of the selected branch from the corresponding source repository. n.b. old commit ids are lost in this process - so don't count on being able to reference your new repository with old commit ids.

Each commit message will be retained, but prepended with the name of the source repository.

`git log --oneline --graph --decorate`

```
* c91baa3 (HEAD -> master, origin/master) repo3: git-join-repos monolithic conversion merge
|\
|\
| * 106a74c repo3: add keyed message storage
| * c48e9f2 repo3: add build/.npmignore
| * 2766e11 repo3: fix build/.gitignore
| * dcef023 repo3: initial commit of repo3
* b7530e7 newname: git-join-repos monolithic conversion merge
|\
|\
| * 02f3536 newname: update sublibrary to versionf 1.4
...
```
Expand Down
16 changes: 10 additions & 6 deletions git-join-repos
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ data_file="$1"
name_urls="$(cat $data_file)"
repo_name=
repo_url=
repo_branch=

function empty_repo_or_die {
total="$(git count-objects -v | cut -d' ' -f2 | awk '{s+=$1}END{print s}')"
Expand All @@ -36,17 +37,20 @@ function empty_repo_or_die {
}

function split_line {
repo_name="${a% *}"
repo_url="${a#* }"
readarray -d" " -t parts < <(echo -n "$a")
repo_name="${parts[0]}"
repo_url="${parts[1]}"
repo_branch="${parts[2]:-master}"
}

function repo_master_to_subdir {
git filter-branch -f --index-filter \
git filter-branch -f --prune-empty --tag-name-filter cat -- --all
git filter-branch -f --tag-name-filter cat --index-filter \
"git ls-files -s | ${sed} \"s|\t\\\"*|&${repo_name}/|\" |
GIT_INDEX_FILE=\$GIT_INDEX_FILE.new git update-index --index-info &&
mv \"\$GIT_INDEX_FILE.new\" \"\$GIT_INDEX_FILE\"" HEAD

git filter-branch -f --msg-filter "/bin/echo -n \"${repo_name}: \" && cat"
git filter-branch -f --tag-name-filter cat --msg-filter "/bin/echo -n \"${repo_name}: \" && cat"

}

Expand All @@ -59,7 +63,7 @@ for a in $name_urls; do
git rm -qrf --ignore-unmatch .
git remote add "$repo_name" "$repo_url"
git fetch "$repo_name"
git merge "$repo_name/master"
git merge "$repo_name/${repo_branch}"
repo_master_to_subdir
git remote remove "$repo_name"
done
Expand All @@ -70,6 +74,6 @@ git rm -qrf --ignore-unmatch .
for a in $name_urls; do
split_line "$a"

git merge --allow-unrelated-histories --ff -m "$repo_name: $self_name monolithic conversion merge" "$repo_name"
git merge --allow-unrelated-histories --ff -m "$self_name: merge ${repo_name}[${repo_branch}]" "$repo_name"
git branch -D "$repo_name"
done