여러 자식 리포지토리 결합
다음과 같은 설정이 있다고 가정 해 봅시다.
phd/code/
phd/figures/
phd/thesis/
역사적 이유로, 이들은 모두 자신의 자식 저장소를 가지고 있습니다. 그러나 나는 그것들을 하나의 것으로 결합하여 사물을 조금 단순화하고 싶습니다. 예를 들어 지금 당장 두 가지 설정을 변경하고 다음과 같은 작업을 수행해야합니다.
cd phd/code
git commit
cd ../figures
git commit
그냥 수행하는 것이 좋을 것입니다.
cd phd
git commit
하위 모듈을 사용하거나 하위 리포지토리에서 가져 오는 두 가지 방법이 있지만 내가 찾는 것보다 조금 더 복잡합니다. 최소한 나는 행복 할 것이다
cd phd
git init
git add [[everything that's already in my other repositories]]
그러나 그것은 하나의 라이너처럼 보이지 않습니다. 거기에 무엇인가 git
가 나를 도울 수 있습니까?
여기 내가 준 해결책이 있습니다 .
먼저 phd 디렉토리의 전체 백업을 수행하십시오. 수년간의 노력으로 잃어버린 책임을지지 않기를 바랍니다! ;-)
$ cp -r phd phd-backup
의 내용 이동
phd/code
에를phd/code/code
, 그리고 그것이 항상 (이 용도의 자식의이 계속 것처럼 보이도록 역사를 수정 필터 분기 명령) :$ cd phd/code $ git filter-branch --index-filter \ 'git ls-files -s | sed "s#\t#&code/#" | GIT_INDEX_FILE=$GIT_INDEX_FILE.new \ git update-index --index-info && mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' HEAD
의 내용에 대해 동일
phd/figures
하고phd/thesis
(다만 교체code
로figures
하고thesis
).이제 디렉토리 구조는 다음과 같아야합니다.
phd |_code | |_.git | |_code | |_(your code...) |_figures | |_.git | |_figures | |_(your figures...) |_thesis |_.git |_thesis |_(your thesis...)
그런 다음 루트 디렉토리에 git 저장소를 작성하고 모든 것을 가져 와서 이전 저장소를 제거하십시오.
$ cd phd $ git init $ git pull code $ rm -rf code/code $ rm -rf code/.git $ git pull figures --allow-unrelated-histories $ rm -rf figures/figures $ rm -rf figures/.git $ git pull thesis --allow-unrelated-histories $ rm -rf thesis/thesis $ rm -rf thesis/.git
마지막으로 원하는 것을 갖추어야합니다.
phd |_.git |_code | |_(your code...) |_figures | |_(your figures...) |_thesis |_(your thesis...)
이 절차의 한 가지 좋은 점은 버전이 지정되지 않은 파일과 디렉토리를 그대로 둡니다 .
도움이 되었기를 바랍니다.
Just one word of warning though: if your code
directory already has a code
subdirectory or file, things might go very wrong (same for figures
and thesis
of course). If that's the case, just rename that directory or file before going through this whole procedure:
$ cd phd/code
$ git mv code code-repository-migration
$ git commit -m "preparing the code directory for migration"
And when the procedure is finished, add this final step:
$ cd phd
$ git mv code/code-repository-migration code/code
$ git commit -m "final step for code directory migration"
Of course, if the code
subdirectory or file is not versioned, just use mv
instead of git mv
, and forget about the git commit
s.
git-stitch-repo
will process the output ofgit-fast-export --all --date-order
on the git repositories given on the command-line, and create a stream suitable forgit-fast-import
that will create a new repository containing all the commits in a new commit tree that respects the history of all the source repositories.
Perhaps, simply (similarly to the previous answer, but using simpler commands) making in each of the separate old repositories a commit that moves the content into a suitably named subdir, e.g.:
$ cd phd/code
$ mkdir code
# This won't work literally, because * would also match the new code/ subdir, but you understand what I mean:
$ git mv * code/
$ git commit -m "preparing the code directory for migration"
and then merging the three separate repos into one new, by doing smth like:
$ cd ../..
$ mkdir phd.all
$ cd phd.all
$ git init
$ git pull ../phd/code
...
Then you'll save your histories, but will go on with a single repo.
You could try the subtree merge strategy. It will let you merge repo B into repo A. The advantage over git-filter-branch
is it doesn't require you to rewrite your history of repo A (breaking SHA1 sums).
The git-filter-branch solution works well, but note that if your git repo comes from a SVN import it may fail with a message like:
Rewrite 422a38a0e9d2c61098b98e6c56213ac83b7bacc2 (1/42)mv: cannot stat `/home/.../wikis/nodows/.git-rewrite/t/../index.new': No such file or directory
In this case you need to exclude the initial revision from the filter-branch - i.e. change the HEAD
at the end to [SHA of 2nd revision]..HEAD
- see:
http://www.git.code-experiments.com/blog/2010/03/merging-git-repositories.html
@MiniQuark solution helped me a lot, but unfortunately it doesn't take into account tags which are in source repositories (At least in my case). Below is my improvement to @MiniQuark answer.
First create directory which will contain composed repo and merged repos, create directory for each merged one.
$ mkdir new_phd
$ mkdir new_phd/code
$ mkdir new_phd/figures
$ mkdir new_phd/thesisDo a pull of each repository and fetch all tags. (Presenting instructions only for
code
sub-directory)$ cd new_phd/code
$ git init
$ git pull ../../original_phd/code master
$ git fetch ../../original_phd/code refs/tags/*:refs/tags/*(This is improvement to point 2 in MiniQuark answer) Move the content of
new_phd/code
tonew_phd/code/code
and addcode_
prefeix before each tag$ git filter-branch --index-filter 'git ls-files -s | sed "s-\t\"*-&code/-" | GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' --tag-name-filter 'sed "s-.*-code_&-"' HEAD
After doing so there will be twice as many tags as it was before doing filter-branch. Old tags remain in repo and new tags with
code_
prefix are added.$ git tag
mytag1
code_mytag1Remove old tags manually:
$ ls .git/refs/tags/* | grep -v "/code_" | xargs rm
Repeat point 2,3,4 for other subdirectories
Now we have structure of directories as in @MiniQuark anwser point 3.
Do as in point 4 of MiniQuark anwser, but after doing a pull and before removing
.git
dir, fetch tags:$ git fetch catalog refs/tags/*:refs/tags/*
Continue..
This is just another solution. Hope it helps someone, it helped me :)
git-stitch-repo from Aristotle Pagaltzis' answer only works for repositories with simple, linear history.
MiniQuark's answer works for all repositories, but it does not handle tags and branches.
I created a program that works the same way as MiniQuark describes, but it uses one merge commit (with N parents) and also recreates all tags and branches to point to these merge commits.
See the git-merge-repos repository for examples how to use it.
I have created a tool that make this task. The method used is similar (internally make some things like --filter-branch) but is more friendly. Is GPL 2.0
http://github.com/geppo12/GitCombineRepo
Actually, git-stitch-repo now supports branches and tags, including annotated tags (I found there was a bug which I reported, and it got fixed). What i found useful is with tags. Since tags are attached to commits, and some of the solutions (like Eric Lee's approach) fails to deal with tags. You try to create a branch off an imported tag, and it will undo any git merges/moves and sends you back like the consolidated repository being near identical to the repository that the tag came from. Also, there are issues if you use the same tag across multiple repositories that you 'merged/consolidated'. For example, if you have repo's A ad B, both having tag rel_1.0. You merge repo A and repo B into repo AB. Since rel_1.0 tags are on two different commits (one for A and one for B), which tag will be visible in AB? Either the tag from the imported repo A or from imported repo B, but not both.
git-stitch-repo helps to address that problem by creating rel_1.0-A and rel_1.0-B tags. You may not be able to checkout rel_1.0 tag and expect both, but at least you can see both, and theoretically, you can merge them into a common local branch then create a rel_1.0 tag on that merged branch (assuming you just merge and not change source code). It's better to work with branches, as you can merge like branches from each repo into local branches. (dev-a and dev-b can be merged into a local dev branch which can then be pushed to origin).
The sequence you suggested
git init
git add *
git commit -a -m "import everything"
will work, but you will lose your commit history.
To merge a secondProject within a mainProject:
A) In the secondProject
git fast-export --all --date-order > /tmp/secondProjectExport
B) In the mainProject:
git checkout -b secondProject
git fast-import --force < /tmp/secondProjectExport
In this branch do all heavy transformation you need to do and commit them.
C) Then back to the master and a classical merge between the two branches:
git checkout master
git merge secondProject
I'll throw my solution in here too. It's basically a fairly simple bash script wrapper around git filter-branch
. Like other solutions it only migrates master branches and doesn't migrate tags. But the full master commit histories are migrated and it is a short bash script so it should be relatively easy for users to review or tweak.
https://github.com/Oakleon/git-join-repos
This bash script works around the sed tab character issue (on MacOS for example) and the issue of missing files.
export SUBREPO="subrepo"; # <= your subrepository name here
export TABULATOR=`printf '\t'`;
FILTER='git ls-files -s | sed "s#${TABULATOR}#&${SUBREPO}/#" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
if [ -f "$GIT_INDEX_FILE.new" ]; then mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE; else echo "git filter skipped missing file: $GIT_INXEX_FILE.new"; fi'
git filter-branch --index-filter "$FILTER" HEAD
This is a combination of miniquark, marius-butuc and ryan's posts. Cheers to them!
참고URL : https://stackoverflow.com/questions/277029/combining-multiple-git-repositories
'Programing' 카테고리의 다른 글
Symfony 2.x에서 모든 것이 실제로 번들이어야합니까? (0) | 2020.05.07 |
---|---|
자식 요소에 영향을주지 않고 배경 이미지의 불투명도 설정 (0) | 2020.05.07 |
Visual Basic 6.0과 VBA의 차이점 (0) | 2020.05.07 |
이 HTML에서 3D는 무엇입니까? (0) | 2020.05.07 |
docker와 docker-compose의 차이점은 무엇입니까 (0) | 2020.05.07 |