ඔබ Git ගබඩාවන් දෙකක් ඒකාබද්ධ කරන්නේ කෙසේද?


1643

පහත දැක්වෙන අවස්ථාව සලකා බලන්න:

මම කුඩා Git ව්‍යාපෘතියක් එහි Git repo තුළ සංවර්ධනය කර ඇත්තෙමි. එය දැන් පරිණත වී ඇති අතර, මම කැමතියි A විශාල ව්‍යාපෘතියේ කොටසක් වීමට, එහි විශාල ගබඩාවක් ඇත. මම දැන් B හි උප බහලුමක් ලෙස A එකතු කිරීමට කැමතියි.

කිසිදු පැත්තකින් ඉතිහාසය අහිමි නොවී මම A සමඟ B ඒකාබද්ධ කරන්නේ කෙසේද?


8
: ඔබ එක් බවට නිධි දෙකක් ඒකාබද්ධ කිරීමට, නිධි දෙකම තබා ගැනීමට යාමකින් තොරව, මෙම ප්රශ්නය බලන්න කියලා උත්සාහ කරන්නේ නම් stackoverflow.com/questions/13040958/...
Flimm

සියළුම කොමිට් සුරැකීම සමඟ අභිරුචි ඩිර් හි git repo ඒකාබද්ධ කිරීම සඳහා stackoverflow.com/a/43340714/1772410 භාවිතා කරන්න
ඇන්ඩ්‍රි ඉස්මාන්

Answers:


442

වෙනත් ගබඩාවක තනි ශාඛාවක් එහි ඉතිහාසය රඳවා ගනිමින් උප බහලුමක් යටතේ පහසුවෙන් තැබිය හැකිය. උදාහරණයක් වශයෙන්:

git subtree add --prefix=rails git://github.com/rails/rails.git master

රේල්ස් මාස්ටර් ශාඛාවේ සියලුම ලිපිගොනු "රේල් පීලි" නාමාවලියට එක් කරන තනි බැඳීමක් ලෙස මෙය දිස්වනු ඇත. කෙසේ වෙතත්, බැඳීමේ මාතෘකාවෙහි පැරණි ඉතිහාස වෘක්ෂයට යොමු දැක්වීමක් අඩංගු වේ:

කැපවීමෙන් 'රේල් පීලි /' එකතු කරන්න <rev>

කොහෙද <rev>SHA-1 commit hash. ඔබට තවමත් ඉතිහාසය දැකිය හැකිය, සමහර වෙනස්කම් වලට දොස් කියන්න.

git log <rev>
git blame <rev> -- README.md

මෙය පැරණි පැරණි ශාඛාවක් නොවෙනස්ව පවතින බැවින් ඔබට මෙහි සිට නාමාවලි උපසර්ගය දැකිය නොහැකි බව සලකන්න. ඔබ මෙය සාමාන්‍ය ලිපිගොනු චලනයක් ලෙස සැලකිය යුතුය: එය වෙත ළඟා වන විට ඔබට අමතර පැනීමක් අවශ්‍ය වේ.

# finishes with all files added at once commit
git log rails/README.md

# then continue from original tree
git log <rev> -- README.md

මෙය අතින් සිදු කිරීම හෝ වෙනත් පිළිතුරු වල විස්තර කර ඇති පරිදි ඉතිහාසය නැවත ලිවීම වැනි වඩාත් සංකීර්ණ විසඳුම් තිබේ.

Git-subtree විධානය නිල git-දායකත්වයේ කොටසකි, සමහර පැකට් කළමනාකරුවන් එය පෙරනිමියෙන් ස්ථාපනය කරයි (OS X Homebrew). නමුත් git වලට අමතරව ඔබට එය තනිවම ස්ථාපනය කිරීමට සිදුවනු ඇත.


2
: මෙහි (2013 ජූනි මස වන) Git subtree ස්ථාපනය කරන ආකාරය සම්බන්ධයෙන් උපදෙස් වේ stackoverflow.com/a/11613541/694469 (සහ මම වෙනුවට git co v1.7.11.3 සමග ... v1.8.3).
කජ්මැග්නස්

1
පහත පිළිතුර ගැන හිස ඔසවා තැබීමට ස්තූතියි. Git 1.8.4 වන විට 'subtree' තවමත් ඇතුළත් කර නොමැත (අවම වශයෙන් උබුන්ටු 12.04 git ppa (ppa: git-core / ppa) හි නොමැත)
මැට් ක්ලයින්

1
මෙයින් පසුව, git log rails/somefileඒකාබද්ධ කිරීමේ කැපවීම හැර, එම ගොනුවේ ඉතිහාසය පිළිබඳ ඉතිහාසය නොපෙන්වන බව මට තහවුරු කළ හැකිය . @Artfulrobot යෝජනා කළ පරිදි, ග්‍රෙග් හෙව්ගිල්ගේ පිළිතුර පරීක්ෂා කරන්න . ඔබට ඇතුළත් කිරීමට අවශ්‍ය git filter-branchrepo හි භාවිතා කිරීමට ඔබට අවශ්‍ය විය හැකිය.
ජිෆෙන් ෂැං

6
නැතහොත් එරික් ලීගේ “ගොනු ඉතිහාසය නැති නොකර Git නිධිය දෙකක් එක් ගබඩාවකට ඒකාබද්ධ කිරීම
ජිෆෙන් ෂැං

5
අනෙක් අය පවසා ඇති පරිදි, git subtreeඔබ සිතන දේ නොකරන්න! වඩාත් සම්පූර්ණ විසඳුමක් සඳහා මෙහි බලන්න .
පෝල් ඩ්‍රැපර්

1932

ඔබ ඒකාබද්ධ කිරීමට අවශ්ය නම් project-aසොයා project-b:

cd path/to/project-b
git remote add project-a path/to/project-a
git fetch project-a --tags
git merge --allow-unrelated-histories project-a/master # or whichever branch you want to merge
git remote remove project-a

ලබා ගත්: git විවිධ ගබඩාවන් ඒකාබද්ධ කිරීම?

මෙම ක්‍රමය මට ඉතා හොඳින් ක්‍රියාත්මක විය, එය කෙටි වන අතර මගේ මතය අනුව බොහෝ පිරිසිදුකාරකය.

නඩුව ඔබ දමා ගැනීමට අවශ්ය project-aබහලුමක් බවට, ඔබ භාවිතා කළ හැකිය git-filter-repo( filter-branchතිබේ අධෛර්යමත් ). ඉහත විධානයන්ට පෙර පහත විධානයන් ක්‍රියාත්මක කරන්න:

cd path/to/project-a
git filter-repo --to-subdirectory-filter project-a

විශාල ගබඩාවන් 2 ක් ඒකාබද්ධ කිරීම සඳහා උදාහරණයක්, ඒවායින් එකක් උප බහලුමකට ඇතුළත් කිරීම: https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731

සටහන: මෙම --allow-unrelated-historiesGIT> = 2.9 සිට පමණක් පරාමිතිය පවතී. ශුද්ධාසනයේ Git - GIT ඒකාබද්ධ Documentation / --allow-අසම්බන්ධිත-ඉතිහාස

යාවත්කාලීන කිරීම : --tagsටැග් තබා ගැනීම සඳහා stjstadler විසින් යෝජනා කරන ලද පරිදි එකතු කරන ලදි.


8
මෙය මට ව්‍යාපාරය විය. .Gitignore ගොනුවේ එක් ගැටුමක් සමඟ පළමු වරට චාම් ලෙස ක්‍රියා කළේය! එය කැපවීමේ ඉතිහාසය මනාව ආරක්ෂා කළේය. වෙනත් ප්‍රවේශයන්ට වඩා විශාල ප්ලස් - සරලත්වයට අමතරව - මේ සමඟ ඒකාබද්ධ කරන ලද රෙපෝව පිළිබඳ අඛණ්ඩ සඳහනක් අවශ්‍ය නොවේ. කෙසේ වෙතත් අවධානයෙන් සිටිය යුතු එක් දෙයක් - ඔබ මා වැනි iOS සංවර්ධකයෙකු නම් - ඉලක්කගත රෙපෝ හි ව්‍යාපෘති ගොනුව වැඩබිම තුළට දැමීමට ඉතා ප්‍රවේශම් විය යුතුය.
මැක්ස් මැක්ලියෝඩ්

31
ස්තූතියි. මා වෙනුවෙන් වැඩ කළා. ඒකාබද්ධ කළ නාමාවලිය උප ෆෝල්ඩරයකට ගෙනයාමට මට අවශ්‍ය විය, එබැවින් ඉහත පියවර අනුගමනය කිරීමෙන් පසුව මම සරලවම භාවිතා කළෙමිgit mv source-dir/ dest/new-source-dir
සිද්

14
මෙහි git mergeපියවර අසමත් වේ fatal: refusing to merge unrelated histories; --allow-unrelated-historiesදී මෙන්, පැහැදිලි බව නිවැරදි කිරීම් ලේඛන .
ssc

20
--allow-unrelated-historiesgit 2.9 හි හඳුන්වා දෙන ලදී . පෙර සංස්කරණ වලදී එය පෙරනිමි හැසිරීමකි.
ඩග්ලස් රොයි ds ්ස්

11
කෙටි: git fetch /path/to/project-a master; git merge --allow-unrelated-histories FETCH_HEAD.
jthill

614

කළ හැකි විසඳුම් දෙකක් මෙන්න:

උප මොඩියුල

එක්කෝ නිධිය A විශාල ව්‍යාපෘතියේ වෙනම නාමාවලියකට පිටපත් කරන්න, නැතහොත් (සමහර විට වඩා හොඳ) ක්ලෝන නිධිය A ව්‍යාපෘතියේ උප බහලුමකට පිටපත් කරන්න. ඉන්පසු git subodule භාවිතා කර මෙම ගබඩාව නිධියෙහි උප මොඩියුලයක් බවට පත් කරන්න.

ලිහිල්ව සම්බන්ධ වූ නිධි සඳහා මෙය හොඳ විසඳුමක් වන අතර, නිධිය A හි සංවර්ධනය අඛණ්ඩව සිදුවන අතර සංවර්ධනයේ ප්‍රධාන කොටස A හි වෙනම තනිවම සංවර්ධනයකි. Git Wiki හි SubmoduleSupport සහ GitSubmoduleTutorial පිටුද බලන්න.

උපසිරැසි ඒකාබද්ධ කිරීම

උප ගබඩාව ඒකාබද්ධ කිරීමේ ක්‍රමෝපාය භාවිතා කරමින් නිධිය A ව්‍යාපෘතිය B හි උප බහලුමකට ඒකාබද්ධ කළ හැකිය. මෙය මාකස් ප්‍රින්ස් විසින් සබ්ට්‍රී ඒකාබද්ධ කිරීම සහ ඔබ විස්තර කර ඇත .

git remote add -f Bproject /path/to/B
git merge -s ours --allow-unrelated-histories --no-commit Bproject/master
git read-tree --prefix=dir-B/ -u Bproject/master
git commit -m "Merge B project as our subdirectory"
git pull -s subtree Bproject master

( --allow-unrelated-historiesGit> = 2.9.0 සඳහා විකල්පය අවශ්‍ය වේ.)

නැතහොත් ඔබට ඔහුගේ බ්ලොග් සටහනේ නිදසුනක් ලෙස ප්‍රකාශයට පත් කරන ලද apenwarr (Avery Pennarun) විසින් git subtree මෙවලම ( GitHub හි නිධිය ) භාවිතා කළ හැකිය. Git subodules සඳහා නව විකල්පයක්: git subtree .


මම හිතන්නේ ඔබේ නඩුවේදී (A යනු විශාල ව්‍යාපෘතියේ කොටසක් විය යුතුය) නිවැරදි විසඳුම වනුයේ උප- ඒකාබද්ධ කිරීම භාවිතා කිරීමයි .


1
මෙය ක්‍රියාත්මක වන අතර ඉතිහාසය සුරකින බවක් පෙනේ, නමුත් ඔබට එය ගොනු වෙනස් කිරීමට හෝ ඒකාබද්ධ කිරීම හරහා වෙන් කිරීමට භාවිතා කළ හැකිය. මට පියවරක් මග හැරී තිබේද?
jettero

56
මෙය අසම්පූර්ණයි . ඔව්, ඔබට කොමිස් විශාල ප්‍රමාණයක් ලැබෙනු ඇත, නමුත් ඒවා තවදුරටත් නිවැරදි මාර්ග වෙත යොමු නොවේ. git log dir-B/somefileඑක ඒකාබද්ධ කිරීම හැර වෙන කිසිවක් පෙන්වන්නේ නැත. බලන්න ග්රෙග් Hewgill පිළිතුර යොමු මෙම වැදගත් ප්රශ්නය.
artfulrobot

2
වැදගත්: git pull --no-rebase -s subtree Bproject master ඔබ එය නොකරන්නේ නම් සහ ස්වයංක්‍රීයව නැවත ප්‍රතිස්ථාපනය කිරීමට ඔබ අදින්නේ නම්, ඔබ අවසන් වන්නේ “වස්තුව විග්‍රහ කිරීමට නොහැකි” යනුවෙනි. Osdir.com/ml/git/2009-07/msg01576.html
එරික් බොව්මන් -

4
මෙම පිළිතුර අවුල් සහගත විය හැකිය. මන්දයත් එය ඒකාබද්ධ වූ උප කුලකයක් ලෙස B ඇති බැවින් එය A යන ප්‍රශ්නයේදී ය. පිටපතක් හා පේස්ට් වල ප්‍රති ult ලය?
vfclists

11
ඔබ නිධිය දෙකක් එකට මැලියම් කිරීමට උත්සාහ කරන්නේ නම්, උප මොඩියුල සහ උප ට්‍රී ඒකාබද්ධ කිරීම භාවිතා කිරීම වැරදි මෙවලමකි, මන්ද ඒවා ගොනු ලිපිගොනු සියල්ලම සංරක්ෂණය නොකරන බැවිනි (වෙනත් විචාරකයින් සඳහන් කළ පරිදි). Stackoverflow.com/questions/13040958/… බලන්න .
එරික් ලී

195

ඔබට ව්‍යාපෘතිය වෙන වෙනම නඩත්තු කිරීමට අවශ්‍ය නම් උප මොඩියුලයේ ප්‍රවේශය හොඳයි. කෙසේ වෙතත්, ඔබට සැබවින්ම ව්‍යාපෘති දෙකම එකම ගබඩාවකට ඒකාබද්ධ කිරීමට අවශ්‍ය නම්, ඔබට තව ටිකක් වැඩ කිරීමට තිබේ.

පළමු දෙය git filter-branchනම් දෙවන ගබඩාවේ ඇති සියල්ලේ නම් නැවත ලිවීමට භාවිතා කිරීම උප බහලුම තුළ තිබීමයි. ඒ නිසා වෙනුවට foo.c, bar.html, ඔබ හැම projb/foo.cඅතර projb/bar.html.

එවිට, ඔබට පහත සඳහන් දේ වැනි දෙයක් කිරීමට හැකි විය යුතුය:

git remote add projb [wherever]
git pull projb

මෙම git pullඉතා නැහැ ඇත git fetchවිසින් අනුගමනය git merge. ඔබ ඇදගෙන යන ගබඩාවට තවමත් projb/නාමාවලියක් නොමැති නම් ගැටුම් ඇති නොවිය යුතුය .

තවදුරටත් විමසිලිමත් සමාන දෙයක් ඒකාබද්ධ කිරීමට සිදු වූ බවයි gitkබවට git. ජූනියෝ සී හමානෝ ඒ ගැන මෙහි ලියයි: http://www.mail-archive.com/git@vger.kernel.org/msg03395.html


4
subtree ඒකාබද්ධ කිරීම වඩා හොඳ විසඳුමක් වන අතර ඇතුළත් කළ ව්‍යාපෘතියේ ඉතිහාසය නැවත ලිවීම අවශ්‍ය නොවේ
Jakub Narębski

8
git filter-branchමෙය සාක්ෂාත් කර ගැනීම සඳහා භාවිතා කරන්නේ කෙසේදැයි දැන ගැනීමට මම කැමතියි . මෑන් පිටුවේ එය ප්‍රතිවිරුද්ධ මාර්ගය ගැන කියයි: උප ඩිර් / මූල බවට පත් කිරීම, නමුත් අනෙක් පැත්තෙන් නොවේ.
artfulrobot

31
අපේක්ෂිත
ප්‍රති result ලය

14
පෙරහන් ශාඛාව භාවිතා කරන්නේ කෙසේදැයි මම මෙහි සොයා ගතිමි
ඩේවිඩ් මයිනර්

3
ග්‍රෙග්ගේ දළ සටහන ක්‍රියාත්මක කිරීම සඳහා මෙම පිළිතුර බලන්න .
පෝල් ඩ්‍රැපර්

75

git-subtree හොඳයි, නමුත් එය බොහෝ විට ඔබට අවශ්‍ය එකක් නොවේ.

උදාහරණයක් ලෙස, projectAB හි සාදන ලද නාමාවලිය නම් , පසුව git subtree,

git log projectA

ලැයිස්තුගත කරන්නේ එක් බැඳීමක් පමණි : ඒකාබද්ධ කිරීම. ඒකාබද්ධ කරන ලද ව්‍යාපෘතියෙන් ලැබෙන කොමිස් විවිධ මාර්ග සඳහා වන බැවින් ඒවා නොපෙන්වයි.

ග්‍රෙග් හෙව්ගිල්ගේ පිළිතුර කිට්ටුම ය, එය සත්‍ය වශයෙන්ම මාර්ග නැවත ලියන්නේ කෙසේදැයි නොකියයි.


විසඳුම පුදුම සහගත ලෙස සරල ය.

(1) ඒ,

PREFIX=projectA #adjust this

git filter-branch --index-filter '
    git ls-files -s |
    sed "s,\t,&'"$PREFIX"'/," |
    GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info &&
    mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE
' HEAD

සටහන: මෙය ඉතිහාසය නැවත ලියයි, එබැවින් ඔබ මෙම repo A දිගටම භාවිතා කිරීමට අදහස් කරන්නේ නම්, පළමුවෙන්ම එහි ඉවතලන පිටපතක් ක්ලෝන කිරීමට (පිටපත් කිරීමට) ඔබට අවශ්‍ය විය හැකිය.

සටහන ප්‍රතිලාභ: ඔබ ගොනු නාමවල හෝ මාර්ගයේ අසි නොවන අක්ෂර (හෝ සුදු අක්ෂර) භාවිතා කරන අවස්ථාවකදී sed විධානය තුළ ආදේශක ස්ක්‍රිප්ට් වෙනස් කළ යුතුය. එවැනි අවස්ථාවකදී "ls-files -s" විසින් නිපදවන ලද වාර්තාවක් තුළ ගොනු පිහිටීම ආරම්භ වන්නේ උද්ධෘත ලකුණෙනි.

(2) ඉන්පසු B හි ධාවනය කරන්න

git pull path/to/A

වොයිලා! ඔබට projectAබී හි නාමාවලියක් ඇත. ඔබ ධාවනය කරන්නේ නම් git log projectA, ඒ වෙතින් ලැබෙන සියලු කොමිස් ඔබට පෙනෙනු ඇත.


මගේ නඩුවේදී, මට උප බහලුම් දෙකක් අවශ්‍ය විය, projectAසහ projectB. එවැනි අවස්ථාවක, මම B (1) පියවර ද කළෙමි.


1
ඔබේ පිළිතුර stackoverflow.com/a/618113/586086 වෙතින් පිටපත් කළ බවක් පෙනේ ?
මාඕ

1
Nd ඇන්ඩ rew මාඕ, මම හිතන්නේ ... මට ඇත්තටම මතක නැහැ. මම මෙම පිටපත තරමක් භාවිතා කර ඇත.
පෝල් ඩ්‍රැපර්

6
OS X මත වැඩ නොකරන බවත්, ඔබ <tab> ඇතුලත් කළ යුතු බවත් මම එකතු කරමි
මුනීබ් අලි

2
"$GIT_INDEX_FILE"උපුටා දැක්විය යුතුය (දෙවරක්), එසේ නොමැතිනම් මාර්ගයේ අවකාශයන් තිබේ නම් ඔබේ ක්‍රමය අසාර්ථක වනු ඇත.
රොබ් ඩබ්ලිව්

4
ඔබ කල්පනා කරන්නේ නම්, <tab> Ctrl-V <tab>
ඔක්ස් තුළට

48

නිධි දෙකෙහිම එකම ආකාරයේ ලිපිගොනු තිබේ නම් (විවිධ ව්‍යාපෘති සඳහා රේල් නිධිය දෙකක් වැනි), ද්විතීයික ගබඩාවේ දත්ත ඔබේ වර්තමාන ගබඩාවට ලබා ගත හැකිය:

git fetch git://repository.url/repo.git master:branch_name

ඉන්පසු එය වත්මන් ගබඩාවට ඒකාබද්ධ කරන්න:

git merge --allow-unrelated-histories branch_name

ඔබගේ Git අනුවාදය 2.9 ට වඩා කුඩා නම්, ඉවත් කරන්න --allow-unrelated-histories.

මෙයින් පසු ගැටුම් ඇතිවිය හැකිය. උදාහරණයක් ලෙස ඔබට ඒවා විසඳිය හැකිය git mergetool. kdiff3යතුරුපුවරුව සමඟ පමණක් භාවිතා කළ හැකිය, එබැවින් කේතය කියවීමේදී මිනිත්තු කිහිපයක් වැනි ගැටුම් ගොනුවක් 5 ක් ගතවේ.

ඒකාබද්ධ කිරීම අවසන් කිරීමට මතක තබා ගන්න:

git commit

25

ඒකාබද්ධ කිරීම භාවිතා කරන විට මට ඉතිහාසය අහිමි විය, එබැවින් මම නැවත භාවිතා කිරීම අවසන් කළ බැවින් මගේ කාරණයේදී ගබඩාවන් දෙක එකිනෙකට වෙනස් බැවින් සෑම කැපවීමකදීම ඒකාබද්ධ වීම අවසන් නොවේ.

git clone git@gitorious/projA.git projA
git clone git@gitorious/projB.git projB

cd projB
git remote add projA ../projA/
git fetch projA 
git rebase projA/master HEAD

=> ගැටුම් නිරාකරණය කර, අවශ්‍ය තරම් වාර ගණනක් ඉදිරියට යන්න ...

git rebase --continue

මෙය සිදු කිරීමෙන් එක් ව්‍යාපෘතියකට ප්‍රොජා වෙතින් සියලු කොමිස් ඇති අතර ඉන් පසුව ප්‍රොජ්බී වෙතින් ලැබෙන කොමිස්


25

මගේ නඩුවේදී, මට my-pluginගබඩාවක් සහ main-projectගබඩාවක් my-pluginතිබූ අතර, pluginsඋප බහලුම තුළ සෑම විටම සංවර්ධනය කර ඇති බව මවා පෑමට මට අවශ්‍ය විය main-project.

මූලික වශයෙන්, මම my-pluginගබඩාවේ ඉතිහාසය නැවත ලිවූ අතර එමඟින් සියලු සංවර්ධනය plugins/my-pluginඋප බහලුමේ සිදු වූ බව පෙනෙන්නට තිබුණි . එවිට, මම සංවර්ධනය ඉතිහාසය එකතු my-pluginතුලට main-projectඉතිහාසය, සහ එකට ගස් දෙකක් ඒකාබද්ධ. මේ වන plugins/my-pluginවිටත් main-projectගබඩාවේ කිසිදු නාමාවලියක් නොතිබූ බැවින් මෙය ඉතා සුළු ගැටුම් ඒකාබද්ධ කිරීමකි. එහි ප්‍රති ing ලයක් ලෙස නිධිය තුළ මුල් ව්‍යාපෘති දෙකේම ඉතිහාසය අඩංගු වූ අතර එයට මුල් දෙකක් තිබුණි.

ටීඑල්; ඩී.ආර්

$ cp -R my-plugin my-plugin-dirty
$ cd my-plugin-dirty
$ git filter-branch -f --tree-filter "zsh -c 'setopt extended_glob && setopt glob_dots && mkdir -p plugins/my-plugin && (mv ^(.git|plugins) plugins/my-plugin || true)'" -- --all
$ cd ../main-project
$ git checkout master
$ git remote add --fetch my-plugin ../my-plugin-dirty
$ git merge my-plugin/master --allow-unrelated-histories
$ cd ..
$ rm -rf my-plugin-dirty

දිගු අනුවාදය

පළමුව, my-pluginනිධියෙහි පිටපතක් සාදන්න , මන්ද අපි මෙම ගබඩාවේ ඉතිහාසය නැවත ලිවීමට යන බැවිනි.

දැන්, my-pluginගබඩාවේ මූලයට සැරිසැරීම , ඔබේ ප්‍රධාන ශාඛාව (බොහෝ විට master) පරීක්ෂා කර පහත විධානය ක්‍රියාත්මක කරන්න. ඇත්ත වශයෙන්ම, ඔබ වෙනුවෙන් ආදේශ කළ යුතු my-pluginහා pluginsඕනෑම දෙයක් ඔබගේ සත්ය නම් වේ.

$ git filter-branch -f --tree-filter "zsh -c 'setopt extended_glob && setopt glob_dots && mkdir -p plugins/my-plugin && (mv ^(.git|plugins) plugins/my-plugin || true)'" -- --all

දැන් පැහැදිලි කිරීමක් සඳහා. git filter-branch --tree-filter (...) HEADගස්වන්නේ (...)සෑම විධානය සිට ලගා වන බව නසා HEAD. මෙය එක් එක් බැඳීම සඳහා ගබඩා කර ඇති දත්ත මත කෙලින්ම ක්‍රියාත්මක වන බව සලකන්න, එබැවින් “වැඩ කරන නාමාවලිය”, “දර්ශකය”, “වේදිකාගත කිරීම” සහ යනාදිය ගැන අපට කරදර විය යුතු නැත.

ඔබ ක්රියාත්මක කරන්නේ නම් filter-branchඅසමත් විධානය, එය සමහර ගොනු පිටුපස ඉතිරි වනු ඇත .gitනාමාවලිය සහ ඉදිරි කාලය ඔබ උත්සාහ filter-branchඔබ සැපයීමට මිස එය, මේ ගැන පැමිණිලි කරනු ඇත -fකිරීමට විකල්පය filter-branch.

සැබෑ විධානය සඳහා වන ලෙස, මම ලබා බොහෝ වාසනාව නැහැ bashඒ නිසා ඒ වෙනුවට මම භාවිතා මට අවශ්ය දේ කරන්න, zsh -cකරන්න zshඅණ ක්රියාත්මක කිරීම. පළමු මම සකස් extended_globසක්රීය දේ වන විකල්පය, ^(...)තුළ කාරක රීති mvඅණ මෙන්ම, glob_dotsමට dotfiles (වැනි තෝරා ගැනීමට ඉඩ සලසා දෙයි විකල්පය, .gitignoreඉතා glob සමග) ( ^(...)).

ඊළඟට, මම භාවිතා mkdir -pදෙකම නිර්මාණය කිරීමට විධාන pluginsහා plugins/my-pluginඑම අවස්ථාවේ දී.

අවසාන වශයෙන්, මම zsh"negative ණ ග්ලෝබ්" විශේෂාංගය භාවිතා කර ^(.git|plugins)නිධියෙහි මූල නාමාවලියෙහි ඇති සියලුම ලිපිගොනු .gitහා අලුතින් සාදන ලද my-pluginෆෝල්ඩරය හැරුණු විට ගැලපේ . (බැහැර .gitකිරීම මෙහි අවශ්‍ය නොවනු ඇත, නමුත් ඩිරෙක්ටරියක් ඒ තුළට ගෙන යාමට උත්සාහ කිරීම දෝෂයකි.)

මගේ ගබඩාවේ, ආරම්භක බැඳීම කිසිදු ලිපිගොනු ඇතුළත් කර නොතිබූ හෙයින්, mvවිධානය මඟින් ආරම්භක බැඳීමෙහි දෝෂයක් නැවත ලබා දෙන ලදි (ගෙනයාමට කිසිවක් නොමැති බැවින්). ඒ නිසා, මම එකතු || trueඑසේ git filter-branchනොවේ ඉවත්වීම බව.

මෙම --allවිකල්පය මඟින් filter-branchසඳහා ඉතිහාසය සකස්කල සියලු නිධිය තුල ශාඛා, සහ අමතර --කියන්න අවශ්ය gitවෙනුවට සඳහා විකල්පයක් ලෙස, සකස්කල ශාඛා සඳහා වන විකල්පය ලැයිස්තුව කොටසක් ලෙස එය අර්ථ නිරූපණය කිරීමට filter-branchයොමුවෙමු.

දැන්, ඔබේ main-projectගබඩාවට සංචාලනය කර ඔබට ඒකාබද්ධ වීමට අවශ්‍ය ඕනෑම ශාඛාවක් පරීක්ෂා කරන්න. දුරස්ථයක් ලෙස ඔබේ my-pluginගබඩාවේ දේශීය පිටපත (එහි ඉතිහාසය වෙනස් කර ඇති) එක් main-projectකරන්න:

$ git remote add --fetch my-plugin $PATH_TO_MY_PLUGIN_REPOSITORY

ඔබගේ කැපවීමේ ඉතිහාසයේ දැන් ඔබට සම්බන්ධයක් නැති ගස් දෙකක් ඇති අතර, ඒවා භාවිතයෙන් මනාව දෘශ්‍යමාන කළ හැකිය:

$ git log --color --graph --decorate --all

ඒවා ඒකාබද්ධ කිරීම සඳහා, භාවිතා කරන්න:

$ git merge my-plugin/master --allow-unrelated-histories

2.9.0 ට පෙර Git හි --allow-unrelated-historiesවිකල්පය නොපවතින බව සලකන්න . බව එම දෝශ පණිවිඩය: ඔබ එක් අනුවාදයක් භාවිතා කරන්නේ නම්, හුදෙක් විකල්පය පළමුෙවන් --allow-unrelated-historiesකිරීම වළක්වා විය2.9.0 දී වැඩිදුරටත් සඳහන් කළේය.

ඔබට ඒකාබද්ධ කිරීමේ ගැටුම් නොතිබිය යුතුය. ඔබ එසේ කරන්නේ නම්, බොහෝ විට එයින් අදහස් වන්නේ එක්කෝ filter-branchවිධානය නිවැරදිව ක්‍රියා නොකළ බව හෝ දැනටමත් plugins/my-pluginඩිරෙක්ටරියක් තිබී ඇති main-projectබවයි.

මුල් දෙකක් සහිත ගබඩාවක් සෑදීමට හැකරි සිදුවන්නේ කුමක් දැයි කල්පනා කරමින් අනාගත දායකයින් සඳහා පැහැදිලි කිරීමේ පණිවිඩයක් ඇතුළත් කිරීමට වග බලා ගන්න.

ඉහත git logවිධානය භාවිතා කර මූල කොමිට් දෙකක් තිබිය යුතු නව කැපවීමේ ප්‍රස්ථාරය ඔබට දෘශ්‍යමාන කළ හැකිය . ශාඛාව පමණක් masterඒකාබද්ධ වන බව සලකන්න . මෙයින් අදහස් කරන්නේ ඔබට ගසට my-pluginඒකාබද්ධ වීමට අවශ්‍ය වෙනත් ශාඛා පිළිබඳ වැදගත් වැඩක් තිබේ නම් main-project, ඔබ my-pluginමෙම ඒකාබද්ධ කිරීම් සිදු කරන තුරු දුරස්ථය මකා දැමීමෙන් වැළකී සිටිය යුතු බවයි. ඔබ එසේ නොකරන්නේ නම්, එම ශාඛා වලින් ලැබෙන මුදල් තවමත් main-projectගබඩාවේ පවතිනු ඇත, නමුත් සමහර ඒවා ළඟා විය නොහැකි අතර අවසානයේ කසළ එකතු කිරීමට ඉඩ ඇත. (එසේම, ඔබට SHA විසින් ඒවා යොමු කිරීමට සිදුවනු ඇත, මන්ද දුරස්ථයක් මකා දැමීමෙන් එහි දුරස්ථ ලුහුබැඳීමේ ශාඛා ඉවත් වේ.)

විකල්පයක් ලෙස, ඔබට තබා ගැනීමට අවශ්‍ය සියල්ල ඒකාබද්ධ කිරීමෙන් පසුව my-plugin, ඔබට my-pluginදුරස්ථ භාවිතයෙන් ඉවත් කළ හැකිය:

$ git remote remove my-plugin

ඔබ my-pluginඉතිහාසය වෙනස් කළ ගබඩාවේ පිටපත දැන් ඔබට ආරක්ෂිතව මකා දැමිය හැකිය . මගේ නඩුවේදී, my-pluginඒකාබද්ධ කිරීම සම්පුර්ණ කර තල්ලු කිරීමෙන් පසුව මම සැබෑ ගබඩාවට ක්ෂය කිරීමේ දැන්වීමක් එක් කළෙමි .


මැක් ඕඑස් එක්ස් එල් කැපිටන් සමඟ git --version 2.9.0සහ සමඟ පරීක්ෂා කර zsh --version 5.2ඇත. ඔබගේ සැතපුම් ගණන වෙනස් විය හැකිය.

යොමුව:


1
කොහෙන්ද --allow-unrelated-histories?
xpto

3
Ar මාර්සෙලෝ ෆිල්හෝ චෙක්පත man git-merge. පෙරනිමියෙන්, පොදු මුතුන් මිත්තෙකු බෙදා නොගන්නා ඉතිහාසයන් ඒකාබද්ධ කිරීම git merge විධානය ප්‍රතික්ෂේප කරයි. ඔවුන්ගේ ජීවිත ස්වාධීනව ආරම්භ කළ ව්‍යාපෘති දෙකක ඉතිහාසය ඒකාබද්ධ කිරීමේදී මෙම ආරක්ෂාව ඉක්මවා යාමට මෙම විකල්පය භාවිතා කළ හැකිය. එය ඉතා දුර්ලභ අවස්ථාවක් බැවින්, පෙරනිමියෙන් මෙය සක්‍රීය කිරීමට වින්‍යාස විචල්‍යයක් නොපවතින අතර එය එකතු නොවේ.
රේඩන් රොස්බරෝ

ලබා ගත යුතුද git version 2.7.2.windows.1?
xpto

2
ArMarceloFilho මෙය 2.9.0 දී එකතු කරන ලදි, නමුත් පැරණි අනුවාද වලදී ඔබට විකල්පය සමත් නොවිය යුතුය (එය ක්‍රියාත්මක වනු ඇත). github.com/git/git/blob/…
රේඩන් රොස්බරෝ

මෙය හොඳින් ක්‍රියාත්මක විය. ඒකාබද්ධ කිරීමට පෙර ගස තුළ මට අවශ්‍ය ස්ථානයට ගොනු නාම නැවත ලිවීමට පෙරහන් ශාඛාව භාවිතා කිරීමට මට හැකි විය. මාස්ටර් ශාඛාව හැරුණු විට ඉතිහාසය ගෙනයාමට අවශ්‍ය නම් තවත් වැඩ ප්‍රමාණයක් සම්බන්ධ වනු ඇතැයි මම සිතමි.
codeDr

9

මම දින ගණනාවක් තිස්සේ එකම දේ කිරීමට උත්සාහ කරමි, මම git 2.7.2 භාවිතා කරමි. උප කුලකය ඉතිහාසය ආරක්ෂා නොකරයි.

ඔබ නැවත පැරණි ව්‍යාපෘතිය භාවිතා නොකරන්නේ නම් ඔබට මෙම ක්‍රමය භාවිතා කළ හැකිය.

මම යෝජනා කරන්නේ ඔබ මුලින්ම B ශාඛාව හා ශාඛාවේ වැඩ කරන ලෙසයි.

අතු රහිත පියවර මෙන්න:

cd B

# You are going to merge A into B, so first move all of B's files into a sub dir
mkdir B

# Move all files to B, till there is nothing in the dir but .git and B
git mv <files> B

git add .

git commit -m "Moving content of project B in preparation for merge from A"


# Now merge A into B
git remote add -f A <A repo url>

git merge A/<branch>

mkdir A

# move all the files into subdir A, excluding .git
git mv <files> A

git commit -m "Moved A into subdir"


# Move B's files back to root    
git mv B/* ./

rm -rf B

git commit -m "Reset B to original state"

git push

ඔබ දැන් කිසියම් ලිපිගොනු උප ඩිරර් ඒ වෙත ලොග් කළහොත් ඔබට සම්පූර්ණ ඉතිහාසය ලැබෙනු ඇත

git log --follow A/<file>

මෙය කිරීමට මට උපකාර වන තනතුර මෙයයි:

http://saintgimp.org/2013/01/22/merging-two-git-repositories-into-one-repository-without-losing-file-history/


8

ඔබ තුළ ණයකට බී ශාඛා සිට ගොනු තබා ගැනීමට ඔබට අවශ්ය නම් subtree ණයකට ඒ, සහ ද ඉතිහාසය සංරක්ෂණය, කියවීම තබා ගන්න. (පහත උදාහරණයේ දී, මම සිතන්නේ අපට රෙපෝ බී හි ප්‍රධාන ශාඛාව රෙපෝ ඒ හි ප්‍රධාන ශාඛාවට ඒකාබද්ධ කළ යුතු බවයි.)

A repo හි, repo B ලබා ගැනීම සඳහා පළමුව පහත සඳහන් දේ කරන්න:

git remote add B ../B # Add repo B as a new remote.
git fetch B

දැන් අපි හඳුන්වන repo A හි නවතම ශාඛාවක් (එක් කැපවීමක් සහිතව) නිර්මාණය කරමු new_b_root. එහි ප්‍රති commit ලයක් වශයෙන්, රෙපෝ බී හි ප්‍රධාන ශාඛාවේ පළමු කැපවීමේදී සිදු කරන ලද නමුත් උප බහලුමක ඇතුළත් ලිපිගොනු path/to/b-files/ඇත.

git checkout --orphan new_b_root master
git rm -rf . # Remove all files.
git cherry-pick -n `git rev-list --max-parents=0 B/master`
mkdir -p path/to/b-files
git mv README path/to/b-files/
git commit --date="$(git log --format='%ai' $(git rev-list --max-parents=0 B/master))"

පැහැදිලි කිරීම: --orphanපිටවීමේ විධානය සඳහා ඇති විකල්පය A හි ප්‍රධාන ශාඛාවෙන් ලිපිගොනු පරීක්ෂා කරන නමුත් කිසිදු බැඳීමක් ඇති නොකරයි. ඊළඟට අපි කෙසේ හෝ සියලුම ලිපිගොනු ඉවත් කරන නිසා අපට ඕනෑම බැඳීමක් තෝරා ගත හැකිය. ඉන්පසුව, තවමත් ( -n) කැපවීමකින් තොරව , අපි බී හි ප්‍රධාන ශාඛාවෙන් පළමු කැපවීම තෝරා ගනිමු. (චෙරි-පික් මඟින් මුල් පිටවීමේ පණිවිඩය කෙලින්ම පරීක්ෂා කිරීමක් ලෙස නොපෙනේ.) ඉන්පසු අපි සියලු ලිපිගොනු රෙපෝ බී වෙතින් තැබීමට අවශ්‍ය උප කුලකය සාදන්නෙමු. චෙරි-පික් සබ්ට්‍රී වෙත. ඉහත උදාහරණයේ, READMEගෙනයාමට ඇත්තේ ගොනුවක් පමණි . ඉන්පසු අපි අපගේ B-repo root කැපවීම සිදු කරන අතර, ඒ සමඟම, මුල් බැඳීමේ කාලරාමුවද අපි ආරක්ෂා කරමු.

දැන්, අපි B/masterඅලුතින් සාදන ලද මුදුනේ නව ශාඛාවක් සාදන්නෙමු new_b_root. අපි නව ශාඛාව අමතන්නෙමු b:

git checkout -b b B/master
git rebase -s recursive -Xsubtree=path/to/b-files/ new_b_root

දැන්, අපි අපගේ bශාඛාව මෙයට ඒකාබද්ධ කරමු A/master:

git checkout master
git merge --allow-unrelated-histories --no-commit b
git commit -m 'Merge repo B into repo A.'

අවසාන වශයෙන්, ඔබට Bදුරස්ථ හා තාවකාලික ශාඛා ඉවත් කළ හැකිය :

git remote remove B
git branch -D new_b_root b

අවසාන ප්‍රස්ථාරයට මෙවැනි ව්‍යුහයක් ඇත:

රූප විස්තරය මෙහි ඇතුළත් කරන්න


නියම පිළිතුර, ස්තූතියි! උප ඩිරෙක්ටරියට ලොගය නොමැති බව ඇන්ඩ්‍රෙස් සර්ජ් වෙතින් "git subtree" හෝ "merge --allow-සම්බන්ධයක් නැති ඉතිහාසයන්" සමඟ අනෙක් පිළිතුරු මට මග හැරුණි.
ඉලෙන්ඩිර්

8

ස්ටැක් ඕවර්ෆ්ලෝ යනාදිය පිළිබඳව මම මෙහි බොහෝ තොරතුරු එක්රැස් කර ඇති අතර, මට ඇති ගැටළුව විසඳන පිටපතක් එකට දැමීමට මට හැකි වී තිබේ.

අවවාදය නම්, එය එක් එක් ගබඩාවේ 'සංවර්ධනය' ශාඛාව පමණක් සැලකිල්ලට ගෙන එය සම්පූර්ණයෙන්ම නව ගබඩාවක වෙනම නාමාවලියකට ඒකාබද්ධ කිරීමයි.

ටැග් සහ වෙනත් ශාඛා නොසලකා හරිනු ලැබේ - මෙය ඔබට අවශ්‍ය දේ නොවිය හැකිය.

ස්ක්‍රිප්ට් මඟින් විශේෂාංග ශාඛා සහ ටැග් පවා හසුරුවයි - ඒවා නව ව්‍යාපෘතියේ නම් කිරීම මඟින් ඒවා පැමිණියේ කොහෙන්දැයි ඔබ දැන ගනී.

#!/bin/bash
#
################################################################################
## Script to merge multiple git repositories into a new repository
## - The new repository will contain a folder for every merged repository
## - The script adds remotes for every project and then merges in every branch
##   and tag. These are renamed to have the origin project name as a prefix
##
## Usage: mergeGitRepositories.sh <new_project> <my_repo_urls.lst>
## - where <new_project> is the name of the new project to create
## - and <my_repo_urls.lst> is a file contaning the URLs to the respositories
##   which are to be merged on separate lines.
##
## Author: Robert von Burg
##            eitch@eitchnet.ch
##
## Version: 0.3.2
## Created: 2018-02-05
##
################################################################################
#

# disallow using undefined variables
shopt -s -o nounset

# Script variables
declare SCRIPT_NAME="${0##*/}"
declare SCRIPT_DIR="$(cd ${0%/*} ; pwd)"
declare ROOT_DIR="$PWD"
IFS=$'\n'

# Detect proper usage
if [ "$#" -ne "2" ] ; then
  echo -e "ERROR: Usage: $0 <new_project> <my_repo_urls.lst>"
  exit 1
fi


## Script variables
PROJECT_NAME="${1}"
PROJECT_PATH="${ROOT_DIR}/${PROJECT_NAME}"
TIMESTAMP="$(date +%s)"
LOG_FILE="${ROOT_DIR}/${PROJECT_NAME}_merge.${TIMESTAMP}.log"
REPO_FILE="${2}"
REPO_URL_FILE="${ROOT_DIR}/${REPO_FILE}"


# Script functions
function failed() {
  echo -e "ERROR: Merging of projects failed:"
  echo -e "ERROR: Merging of projects failed:" >>${LOG_FILE} 2>&1
  echo -e "$1"
  exit 1
}

function commit_merge() {
  current_branch="$(git symbolic-ref HEAD 2>/dev/null)"
  if [[ ! -f ".git/MERGE_HEAD" ]] ; then
    echo -e "INFO:   No commit required."
    echo -e "INFO:   No commit required." >>${LOG_FILE} 2>&1
  else
    echo -e "INFO:   Committing ${sub_project}..."
    echo -e "INFO:   Committing ${sub_project}..." >>${LOG_FILE} 2>&1
    if ! git commit -m "[Project] Merged branch '$1' of ${sub_project}" >>${LOG_FILE} 2>&1 ; then
      failed "Failed to commit merge of branch '$1' of ${sub_project} into ${current_branch}"
    fi
  fi
}


# Make sure the REPO_URL_FILE exists
if [ ! -e "${REPO_URL_FILE}" ] ; then
  echo -e "ERROR: Repo file ${REPO_URL_FILE} does not exist!"
  exit 1
fi


# Make sure the required directories don't exist
if [ -e "${PROJECT_PATH}" ] ; then
  echo -e "ERROR: Project ${PROJECT_NAME} already exists!"
  exit 1
fi


# create the new project
echo -e "INFO: Logging to ${LOG_FILE}"
echo -e "INFO: Creating new git repository ${PROJECT_NAME}..."
echo -e "INFO: Creating new git repository ${PROJECT_NAME}..." >>${LOG_FILE} 2>&1
echo -e "===================================================="
echo -e "====================================================" >>${LOG_FILE} 2>&1
cd ${ROOT_DIR}
mkdir ${PROJECT_NAME}
cd ${PROJECT_NAME}
git init
echo "Initial Commit" > initial_commit
# Since this is a new repository we need to have at least one commit
# thus were we create temporary file, but we delete it again.
# Deleting it guarantees we don't have conflicts later when merging
git add initial_commit
git commit --quiet -m "[Project] Initial Master Repo Commit"
git rm --quiet initial_commit
git commit --quiet -m "[Project] Initial Master Repo Commit"
echo


# Merge all projects into the branches of this project
echo -e "INFO: Merging projects into new repository..."
echo -e "INFO: Merging projects into new repository..." >>${LOG_FILE} 2>&1
echo -e "===================================================="
echo -e "====================================================" >>${LOG_FILE} 2>&1
for url in $(cat ${REPO_URL_FILE}) ; do

  if [[ "${url:0:1}" == '#' ]] ; then
    continue
  fi

  # extract the name of this project
  export sub_project=${url##*/}
  sub_project=${sub_project%*.git}

  echo -e "INFO: Project ${sub_project}"
  echo -e "INFO: Project ${sub_project}" >>${LOG_FILE} 2>&1
  echo -e "----------------------------------------------------"
  echo -e "----------------------------------------------------" >>${LOG_FILE} 2>&1

  # Fetch the project
  echo -e "INFO:   Fetching ${sub_project}..."
  echo -e "INFO:   Fetching ${sub_project}..." >>${LOG_FILE} 2>&1
  git remote add "${sub_project}" "${url}"
  if ! git fetch --tags --quiet ${sub_project} >>${LOG_FILE} 2>&1 ; then
    failed "Failed to fetch project ${sub_project}"
  fi

  # add remote branches
  echo -e "INFO:   Creating local branches for ${sub_project}..."
  echo -e "INFO:   Creating local branches for ${sub_project}..." >>${LOG_FILE} 2>&1
  while read branch ; do
    branch_ref=$(echo $branch | tr " " "\t" | cut -f 1)
    branch_name=$(echo $branch | tr " " "\t" | cut -f 2 | cut -d / -f 3-)

    echo -e "INFO:   Creating branch ${branch_name}..."
    echo -e "INFO:   Creating branch ${branch_name}..." >>${LOG_FILE} 2>&1

    # create and checkout new merge branch off of master
    if ! git checkout -b "${sub_project}/${branch_name}" master >>${LOG_FILE} 2>&1 ; then failed "Failed preparing ${branch_name}" ; fi
    if ! git reset --hard ; then failed "Failed preparing ${branch_name}" >>${LOG_FILE} 2>&1 ; fi
    if ! git clean -d --force ; then failed "Failed preparing ${branch_name}" >>${LOG_FILE} 2>&1 ; fi

    # Merge the project
    echo -e "INFO:   Merging ${sub_project}..."
    echo -e "INFO:   Merging ${sub_project}..." >>${LOG_FILE} 2>&1
    if ! git merge --allow-unrelated-histories --no-commit "remotes/${sub_project}/${branch_name}" >>${LOG_FILE} 2>&1 ; then
      failed "Failed to merge branch 'remotes/${sub_project}/${branch_name}' from ${sub_project}"
    fi

    # And now see if we need to commit (maybe there was a merge)
    commit_merge "${sub_project}/${branch_name}"

    # relocate projects files into own directory
    if [ "$(ls)" == "${sub_project}" ] ; then
      echo -e "WARN:   Not moving files in branch ${branch_name} of ${sub_project} as already only one root level."
      echo -e "WARN:   Not moving files in branch ${branch_name} of ${sub_project} as already only one root level." >>${LOG_FILE} 2>&1
    else
      echo -e "INFO:   Moving files in branch ${branch_name} of ${sub_project} so we have a single directory..."
      echo -e "INFO:   Moving files in branch ${branch_name} of ${sub_project} so we have a single directory..." >>${LOG_FILE} 2>&1
      mkdir ${sub_project}
      for f in $(ls -a) ; do
        if  [[ "$f" == "${sub_project}" ]] ||
            [[ "$f" == "." ]] ||
            [[ "$f" == ".." ]] ; then
          continue
        fi
        git mv -k "$f" "${sub_project}/"
      done

      # commit the moving
      if ! git commit --quiet -m  "[Project] Move ${sub_project} files into sub directory" ; then
        failed "Failed to commit moving of ${sub_project} files into sub directory"
      fi
    fi
    echo
  done < <(git ls-remote --heads ${sub_project})


  # checkout master of sub probject
  if ! git checkout "${sub_project}/master" >>${LOG_FILE} 2>&1 ; then
    failed "sub_project ${sub_project} is missing master branch!"
  fi

  # copy remote tags
  echo -e "INFO:   Copying tags for ${sub_project}..."
  echo -e "INFO:   Copying tags for ${sub_project}..." >>${LOG_FILE} 2>&1
  while read tag ; do
    tag_ref=$(echo $tag | tr " " "\t" | cut -f 1)
    tag_name_unfixed=$(echo $tag | tr " " "\t" | cut -f 2 | cut -d / -f 3)

    # hack for broken tag names where they are like 1.2.0^{} instead of just 1.2.0
    tag_name="${tag_name_unfixed%%^*}"

    tag_new_name="${sub_project}/${tag_name}"
    echo -e "INFO:     Copying tag ${tag_name_unfixed} to ${tag_new_name} for ref ${tag_ref}..."
    echo -e "INFO:     Copying tag ${tag_name_unfixed} to ${tag_new_name} for ref ${tag_ref}..." >>${LOG_FILE} 2>&1
    if ! git tag "${tag_new_name}" "${tag_ref}" >>${LOG_FILE} 2>&1 ; then
      echo -e "WARN:     Could not copy tag ${tag_name_unfixed} to ${tag_new_name} for ref ${tag_ref}"
      echo -e "WARN:     Could not copy tag ${tag_name_unfixed} to ${tag_new_name} for ref ${tag_ref}" >>${LOG_FILE} 2>&1
    fi
  done < <(git ls-remote --tags --refs ${sub_project})

  # Remove the remote to the old project
  echo -e "INFO:   Removing remote ${sub_project}..."
  echo -e "INFO:   Removing remote ${sub_project}..." >>${LOG_FILE} 2>&1
  git remote rm ${sub_project}

  echo
done


# Now merge all project master branches into new master
git checkout --quiet master
echo -e "INFO: Merging projects master branches into new repository..."
echo -e "INFO: Merging projects master branches into new repository..." >>${LOG_FILE} 2>&1
echo -e "===================================================="
echo -e "====================================================" >>${LOG_FILE} 2>&1
for url in $(cat ${REPO_URL_FILE}) ; do

  if [[ ${url:0:1} == '#' ]] ; then
    continue
  fi

  # extract the name of this project
  export sub_project=${url##*/}
  sub_project=${sub_project%*.git}

  echo -e "INFO:   Merging ${sub_project}..."
  echo -e "INFO:   Merging ${sub_project}..." >>${LOG_FILE} 2>&1
  if ! git merge --allow-unrelated-histories --no-commit "${sub_project}/master" >>${LOG_FILE} 2>&1 ; then
    failed "Failed to merge branch ${sub_project}/master into master"
  fi

  # And now see if we need to commit (maybe there was a merge)
  commit_merge "${sub_project}/master"

  echo
done


# Done
cd ${ROOT_DIR}
echo -e "INFO: Done."
echo -e "INFO: Done." >>${LOG_FILE} 2>&1
echo

exit 0

ඔබට එය http://paste.ubuntu.com/11732805 වෙතින් ද ලබා ගත හැකිය

පළමුව එක් එක් ගබඩාවට URL සමඟ ගොනුවක් සාදන්න, උදා:

git@github.com:eitchnet/ch.eitchnet.parent.git
git@github.com:eitchnet/ch.eitchnet.utils.git
git@github.com:eitchnet/ch.eitchnet.privilege.git

ඉන්පසු ව්‍යාපෘතියේ නමක් සහ පිටපතට යන මාර්ගය ලබා දෙන පිටපත අමතන්න:

./mergeGitRepositories.sh eitchnet_test eitchnet.lst

තිර රචනය තුළම අදහස් රාශියක් ඇති අතර එය කරන්නේ කුමක්ද යන්න පැහැදිලි කළ යුතුය.


පිළිතුරකට පා readers කයන් යොමු කරනවා වෙනුවට, කරුණාකර පිළිතුර මෙහි පළ කරන්න (හෝ එම අදහස් දැක්වීමේදී ඔබ පැවසූ දේ මෙම පිළිතුරට සංස්කරණය කරන්න).
ජොස්ලිබර්

1
නිසැකවම, මා නැවත නොකිරීමට වඩා හොඳ යැයි සිතුවා ... =)
eitch

මෙම ප්‍රශ්නය අනෙක් ප්‍රශ්නයට සමාන යැයි ඔබ සිතන්නේ නම්, ඔබට එය ප්‍රශ්නයට යටින් ඇති “ධජය” සබැඳිය භාවිතා කර අනුපිටපතක් ලෙස සලකුණු කළ හැකි අතර අනෙක් ප්‍රශ්නය දක්වයි. එය අනුපිටපත් ප්‍රශ්නයක් නොව නමුත් ගැටලු දෙකම විසඳීමට එකම පිළිතුරම භාවිතා කළ හැකි යැයි ඔබ සිතන්නේ නම්, එම ප්‍රශ්න දෙකටම එකම පිළිතුරක් පළ කරන්න (ඔබ දැන් කර ඇති පරිදි). දායක වීමට ස්තූතියි!
ජොස්ලිබර්

අරුම පුදුම! වින්ඩෝස් බාෂ් විමසුමේ වැඩ නොකළ නමුත් එය දෝෂ රහිතව උබුන්ටු ධාවනය වන වැග්‍රන්ට් පෙට්ටියක් සාදයි. මොනතරම් කාලය ඉතිරි කරන්නෙක්ද!
xverges


7

එය සිදුවී බොහෝ කලකට පසුව බව මම දනිමි, නමුත් මෙහි මා සොයාගත් අනෙක් පිළිතුරු ගැන මම සතුටු නොවෙමි, එබැවින් මම මෙය ලිවීය:

me=$(basename $0)

TMP=$(mktemp -d /tmp/$me.XXXXXXXX)
echo 
echo "building new repo in $TMP"
echo
sleep 1

set -e

cd $TMP
mkdir new-repo
cd new-repo
    git init
    cd ..

x=0
while [ -n "$1" ]; do
    repo="$1"; shift
    git clone "$repo"
    dirname=$(basename $repo | sed -e 's/\s/-/g')
    if [[ $dirname =~ ^git:.*\.git$ ]]; then
        dirname=$(echo $dirname | sed s/.git$//)
    fi

    cd $dirname
        git remote rm origin
        git filter-branch --tree-filter \
            "(mkdir -p $dirname; find . -maxdepth 1 ! -name . ! -name .git ! -name $dirname -exec mv {} $dirname/ \;)"
        cd ..

    cd new-repo
        git pull --no-commit ../$dirname
        [ $x -gt 0 ] && git commit -m "merge made by $me"
        cd ..

    x=$(( x + 1 ))
done

2
මෙය මා සොයන දේමයි. ස්තූතියි! කෙසේ වෙතත්, මට 22 වන පේළිය වෙනස් කිරීමට සිදු විය:if [[ $dirname =~ ^.*\.git$ ]]; then
හේමන්

2
^. * blarg waste නාස්තිකාර කෑදර RE. .Blarg say කියමින් ඉදිරිපස නැංගුරම මඟ හැරීම හොඳය.
jettero

7

ඔබ නිධිය දෙකක් එකට මැලියම් කිරීමට උත්සාහ කරන්නේ නම්, උප මොඩියුල සහ උප-ට්‍රීට් ඒකාබද්ධ කිරීම භාවිතා කිරීම වැරදි මෙවලමකි, මන්ද ඒවා ගොනු ලිපිගොනු සියල්ලම සංරක්ෂණය නොකරන බැවිනි (මිනිසුන් වෙනත් පිළිතුරු වල සටහන් කර ඇති පරිදි). මෙය කිරීමට සරල හා නිවැරදි ක්‍රමය සඳහා මෙම පිළිතුර මෙතැනින් බලන්න .


1
ඔබේ විසඳුම හොඳින් ක්‍රියාත්මක වන්නේ නව නිධිය සඳහා පමණි, නමුත් ගොනු ගැටුම් සමඟ තවත් එකක repo ඒකාබද්ධ කරන්නේ කෙසේද?
ඇන්ඩ්‍රි ඉස්මාන්

6

මට සමාන අභියෝගයක් තිබුනි, නමුත් මගේ නඩුවේදී, අපි කේතපදයේ එක් සංස්කරණයක් repo A හි සංවර්ධනය කර ඇති අතර, පසුව එය නිෂ්පාදනයේ නව අනුවාදය සඳහා නව repo, repo B බවට ක්ලෝන කළෙමු. රෙපෝ ඒ හි සමහර දෝෂ නිරාකරණය කිරීමෙන් පසුව, අපට රෙපෝ බී බවට කරන ලද වෙනස්කම් එෆ්අයි කිරීමට අවශ්‍ය විය.

  1. Repo A වෙත යොමු කළ B repo වෙත දුරස්ථයක් එක් කිරීම (git remote add ...)
  2. වත්මන් ශාඛාව අදින්න (අපි දෝෂ නිවැරදි කිරීම සඳහා මාස්ටර් භාවිතා කළේ නැත) (git pull remoteForRepoA bugFixBranch)
  3. තල්ලු කිරීම ගිතුබ් සමඟ ඒකාබද්ධ වේ

සංග්‍රහයක් කළා :)


5

@ ස්මාර් හා සමාන නමුත් PRIMARY සහ SECONDARY ලෙස සකසා ඇති ගොනු පද්ධති මාර්ග භාවිතා කරයි:

PRIMARY=~/Code/project1
SECONDARY=~/Code/project2
cd $PRIMARY
git remote add test $SECONDARY && git fetch test
git merge test/master

එවිට ඔබ අතින් ඒකාබද්ධ වේ.

(අනුවර්තනය කරන ලද්දේ අනාර් මනෆොව් විසිනි )


5

ගබඩාවන් 2 ක් ඒකාබද්ධ කිරීම

git clone ssh://<project-repo> project1
cd project1
git remote add -f project2 project2
git merge --allow-unrelated-histories project2/master
git remote rm project2

delete the ref to avoid errors
git update-ref -d refs/remotes/project2/master

4

ඔබ ව්යාපෘති තුනක් හෝ ඊට වඩා වැඩි ඒකාබද්ධ කිරීමට අවශ්ය වූ විට තනි සිදු අනෙක් පිළිතුරු (විස්තර කර ඇති පියවරයන් කරන්න remote add -f, merge). ඉන්පසු, (මෘදු) දර්ශකය පැරණි හිසට නැවත සකසන්න (ඒකාබද්ධ කිරීමක් සිදු නොවූ තැන). සියලුම ලිපිගොනු එකතු කර git add -Aඒවා සිදු කරන්න (පණිවිඩය "ව්‍යාපෘති A, B, C, D එක් ව්‍යාපෘතියකට ඒකාබද්ධ කිරීම) මෙය දැන් මාස්ටර්ගේ කැපවීමේ හැඳුනුම්පතයි.

දැන්, .git/info/graftsපහත සඳහන් අන්තර්ගතයන් සමඟ සාදන්න :

<commit-id of master> <list of commit ids of all parents>

දුවන්න git filter-branch -- head^..head head^2..head head^3..head. ඔබට ශාඛා තුනකට වඩා තිබේ නම්, ඔබට අතු ඇති තරම් එකතු කරන්න head^n..head. ටැග් යාවත්කාලීන කිරීමට, එකතු කරන්න --tag-name-filter cat. සෑම විටම එය එකතු නොකරන්න, මන්ද මෙය සමහර කොමිස් නැවත ලිවීමට හේතු විය හැක. වැඩි විස්තර සඳහා පෙරහන් ශාඛාවේ මෑන් පිටුව බලන්න , “බද්ධ” සොයන්න.

දැන්, ඔබගේ අන්තිම කැපවීමට නිවැරදි දෙමව්පියන් සම්බන්ධ වී ඇත.


1
රැඳී සිටින්න, ව්‍යාපෘති තුනක් එකම කැපවීමකින් ඒකාබද්ධ කිරීමට ඔබට අවශ්‍ය ඇයි?
ස්ටීව් බෙනට්

මම නිධිය, නිධිය-සේවාදායකයා සහ මොඩලර් සමඟ වෙනම git ව්‍යාපෘති ලෙස ආරම්භ කළෙමි. මෙය සම-සේවකයින්ට අපහසු වූ නිසා මම ඔවුන් සමඟ එක් ගිට් ව්‍යාපෘතියකට සම්බන්ධ වීමි. නව ව්‍යාපෘතියේ “මූල” ආරම්භ වන්නේ තවත් ව්‍යාපෘති තුනකින් බව මට දැන ගැනීමට අවශ්‍ය වූයේ තනි ඒකාබද්ධ කිරීමේ කැපවීමක් කිරීමට ය.
කොප්පෝර්

4

A තුළ A ඒකාබද්ධ කිරීම සඳහා:

1) ව්යාපෘතියේ A.

git fast-export --all --date-order > /tmp/ProjectAExport

2) ව්‍යාපෘතියේ බී

git checkout -b projectA
git fast-import --force < /tmp/ProjectAExport

මෙම ශාඛාව තුළ ඔබ විසින් කළ යුතු සියලු මෙහෙයුම් සිදු කර ඒවා සිදු කරන්න.

ඇ) ඉන්පසු නැවත ස්වාමියා වෙත ගොස් ශාඛා දෙක අතර සම්භාව්‍ය ඒකාබද්ධ කිරීමක්:

git checkout master
git merge projectA

2

මෙම ශ්‍රිතය දුරස්ථ repo දේශීය repo dir වෙත ක්ලෝන කරනු ඇත, සියලු කොමිස් ඒකාබද්ධ කිරීමෙන් පසුව සුරකිනු git logඇත, මුල් කොමිස් සහ නිසි මාර්ග පෙන්වනු ඇත:

function git-add-repo
{
    repo="$1"
    dir="$(echo "$2" | sed 's/\/$//')"
    path="$(pwd)"

    tmp="$(mktemp -d)"
    remote="$(echo "$tmp" | sed 's/\///g'| sed 's/\./_/g')"

    git clone "$repo" "$tmp"
    cd "$tmp"

    git filter-branch --index-filter '
        git ls-files -s |
        sed "s,\t,&'"$dir"'/," |
        GIT_INDEX_FILE="$GIT_INDEX_FILE.new" git update-index --index-info &&
        mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
    ' HEAD

    cd "$path"
    git remote add -f "$remote" "file://$tmp/.git"
    git pull "$remote/master"
    git merge --allow-unrelated-histories -m "Merge repo $repo into master" --edit "$remote/master"
    git remote remove "$remote"
    rm -rf "$tmp"
}

භාවිතා කරන්නේ කෙසේද:

cd current/package
git-add-repo https://github.com/example/example dir/to/save

සුළු වෙනස්කම් සිදු කළහොත් ඔබට ඒකාබද්ධ කරන ලද repo හි ගොනු / dirs විවිධ මාර්ග කරා ගෙන යා හැකිය, උදාහරණයක් ලෙස:

repo="https://github.com/example/example"
path="$(pwd)"

tmp="$(mktemp -d)"
remote="$(echo "$tmp" | sed 's/\///g' | sed 's/\./_/g')"

git clone "$repo" "$tmp"
cd "$tmp"

GIT_ADD_STORED=""

function git-mv-store
{
    from="$(echo "$1" | sed 's/\./\\./')"
    to="$(echo "$2" | sed 's/\./\\./')"

    GIT_ADD_STORED+='s,\t'"$from"',\t'"$to"',;'
}

# NOTICE! This paths used for example! Use yours instead!
git-mv-store 'public/index.php' 'public/admin.php'
git-mv-store 'public/data' 'public/x/_data'
git-mv-store 'public/.htaccess' '.htaccess'
git-mv-store 'core/config' 'config/config'
git-mv-store 'core/defines.php' 'defines/defines.php'
git-mv-store 'README.md' 'doc/README.md'
git-mv-store '.gitignore' 'unneeded/.gitignore'

git filter-branch --index-filter '
    git ls-files -s |
    sed "'"$GIT_ADD_STORED"'" |
    GIT_INDEX_FILE="$GIT_INDEX_FILE.new" git update-index --index-info &&
    mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
' HEAD

GIT_ADD_STORED=""

cd "$path"
git remote add -f "$remote" "file://$tmp/.git"
git pull "$remote/master"
git merge --allow-unrelated-histories -m "Merge repo $repo into master" --edit "$remote/master"
git remote remove "$remote"
rm -rf "$tmp"

දැන්වීම්
මාර්ග හරහා ප්‍රතිස්ථාපනය sedවන බැවින් ඒකාබද්ධ කිරීමෙන් පසු එය නිසි මාවත්වල ගමන් කර ඇති බවට වග බලා ගන්න.
මෙම --allow-unrelated-historiesGIT> = 2.9 සිට පමණක් පරාමිතිය පවතී.


1

ලබා දී ඇති විධානය මා යෝජනා කළ හැකි හොඳම විසඳුමයි.

git subtree add --prefix=MY_PROJECT git://github.com/project/my_project.git master

1

මම ව්‍යාපෘති තරමක් අතින් ඒකාබද්ධ කරමි, එමඟින් ඒකාබද්ධ කිරීමේ ගැටුම් සමඟ කටයුතු කිරීමේ අවශ්‍යතාවය මග හැරීමට මට ඉඩ සලසයි.

පළමුව, ඔබට අවශ්‍ය පරිදි අනෙක් ව්‍යාපෘතියෙන් ලිපිගොනු පිටපත් කරන්න.

cp -R myotherproject newdirectory
git add newdirectory

ඉතිහාසයේ ඊළඟ තල්ලුව

git fetch path_or_url_to_other_repo

අවසන් වරට ලබාගත් දේ ඉතිහාසයේ ඒකාබද්ධ කිරීමට git ට කියන්න

echo 'FETCH_HEAD' > .git/MERGE_HEAD

දැන් ඔබ සාමාන්‍යයෙන් කළ යුතු දේ කරන්න

git commit

0

මට අවශ්‍ය වූයේ කුඩා ව්‍යාපෘතියක් විශාල ව්‍යාපෘතියක උප බහලුමකට ගෙන යාමයි. මගේ කුඩා ව්‍යාපෘතියට බොහෝ කොමිස් නොමැති නිසා මම භාවිතා කළෙමි git format-patch --output-directory /path/to/patch-dir. ඊටපස්සේ විශාල ව්‍යාපෘතියේදී මම පාවිච්චි git am --directory=dir/in/project /path/to/patch-dir/*කළා.

මෙම හැඟී මාර්ගය පෙරහනයක්-ශාඛා වඩා අඩු බය හිතෙන හා මාර්ගය වඩා පිරිසිදු. ඇත්ත වශයෙන්ම, එය සියලු අවස්ථාවන්ට අදාළ නොවිය හැකිය.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.