国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

如何合并兩個(gè) Git 存儲(chǔ)庫(kù)?

這篇具有很好參考價(jià)值的文章主要介紹了如何合并兩個(gè) Git 存儲(chǔ)庫(kù)?。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

問(wèn):

考慮以下場(chǎng)景:

我在自己的 Git 存儲(chǔ)庫(kù)中開(kāi)發(fā)了一個(gè)小型實(shí)驗(yàn)項(xiàng)目 A。它現(xiàn)在已經(jīng)成熟,我希望 A 成為更大的項(xiàng)目 B 的一部分,它有自己的大存儲(chǔ)庫(kù)。我現(xiàn)在想將 A 添加為 B 的子目錄。

如何在不丟失任何歷史記錄的情況下將 A 合并到 B 中?

huntsbot.com高效搞錢(qián),一站式跟進(jìn)超10+任務(wù)平臺(tái)外包需求

答1:

打造屬于自己的副業(yè),開(kāi)啟自由職業(yè)之旅,從huntsbot.com開(kāi)始!

如果要將 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 merge different repositories?

這種方法對(duì)我來(lái)說(shuō)效果很好,它更短,在我看來(lái)更干凈。

如果要將 project-a 放入子目錄,可以使用 git-filter-repo(filter-branch 是 discouraged)。在上述命令之前運(yùn)行以下命令:

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

合并 2 個(gè)大型存儲(chǔ)庫(kù)并將其中一個(gè)放入子目錄的示例:https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731

注意: --allow-unrelated-histories 參數(shù)僅在 git >= 2.9 后才存在。請(qǐng)參閱Git - git merge Documentation / --allow-unrelated-histories

更新:按照@jstadler 的建議添加了–tags,以保留標(biāo)簽。

這為我做了生意。第一次像魅力一樣工作,在 .gitignore 文件中只有一個(gè)沖突!它完美地保留了提交歷史。除了簡(jiǎn)單性之外,其他方法的最大優(yōu)點(diǎn)是不需要持續(xù)引用合并的 repo。但是,需要注意的一件事——如果你是像我這樣的 iOS 開(kāi)發(fā)人員——將目標(biāo) repo 的項(xiàng)目文件放入工作區(qū)時(shí)要非常小心。

謝謝。為我工作。我需要將合并的目錄移動(dòng)到一個(gè)子文件夾中,所以按照上述步驟后,我只使用了 git mv source-dir/ dest/new-source-dir

@sg 一種間接的方法是將 project-a 中的所有這些文件移動(dòng)到 project-a 的子目錄中(這樣 project-a 的頂層只有一個(gè)目錄),然后按照上述過(guò)程進(jìn)行操作。

git merge 步驟在此處以 fatal: refusing to merge unrelated histories 失??; --allow-unrelated-histories 修復(fù)了 docs 中所述的問(wèn)題。

更短:git fetch /path/to/project-a master; git merge --allow-unrelated-histories FETCH_HEAD。

答2:

huntsbot.com精選全球7大洲遠(yuǎn)程工作機(jī)會(huì),涵蓋各領(lǐng)域,幫助想要遠(yuǎn)程工作的數(shù)字游民們能更精準(zhǔn)、更高效的找到對(duì)方。

以下是兩種可能的解決方案:

子模塊

將存儲(chǔ)庫(kù) A 復(fù)制到較大項(xiàng)目 B 中的單獨(dú)目錄中,或者(也許更好)將存儲(chǔ)庫(kù) A 克隆到項(xiàng)目 B 中的子目錄中。然后使用 git submodule 將此存儲(chǔ)庫(kù)設(shè)為 子模塊< /strong> 存儲(chǔ)庫(kù) B.

對(duì)于松散耦合的存儲(chǔ)庫(kù)來(lái)說(shuō),這是一個(gè)很好的解決方案,其中存儲(chǔ)庫(kù) A 中的開(kāi)發(fā)繼續(xù)進(jìn)行,并且開(kāi)發(fā)的主要部分是 A 中的單獨(dú)獨(dú)立開(kāi)發(fā)。另請(qǐng)參閱 Git Wiki 上的 SubmoduleSupport 和 GitSubmoduleTutorial 頁(yè)面。

子樹(shù)合并

您可以使用 subtree merge 策略將存儲(chǔ)庫(kù) A 合并到項(xiàng)目 B 的子目錄中。 Markus Prinz 在 Subtree Merging and You 中對(duì)此進(jìn)行了描述。

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

(Git >= 2.9.0 需要選項(xiàng) --allow-unrelated-histories。)

或者您可以使用 apenwarr (Avery Pennarun) 的 git subtree 工具 (repository on GitHub),例如在他的博文 A new alternative to Git submodules: git subtree 中宣布。

我認(rèn)為在您的情況下(A 將成為較大項(xiàng)目 B 的一部分),正確的解決方案是使用子樹(shù)合并。

這有效并且似乎保留了歷史記錄,但不能讓您使用它來(lái)區(qū)分文件或通過(guò)合并一分為二。我錯(cuò)過(guò)了一步嗎?

這是不完整的。是的,您會(huì)收到大量提交,但它們不再引用正確的路徑。 git log dir-B/somefile 除了一個(gè)合并之外不會(huì)顯示任何內(nèi)容。請(qǐng)參閱 Greg Hewgill's answer 引用此重要問(wèn)題。

重要提示: git pull --no-rebase -s subtree Bproject master 如果你不這樣做,并且你已經(jīng)將 pull 設(shè)置為自動(dòng)變基,你最終會(huì)得到“無(wú)法解析對(duì)象”。請(qǐng)參閱osdir.com/ml/git/2009-07/msg01576.html

這個(gè)答案可能會(huì)令人困惑,因?yàn)樗趩?wèn)題中是 A 時(shí)將 B 作為合并的子樹(shù)。復(fù)制和粘貼的結(jié)果?

如果您試圖簡(jiǎn)單地將兩個(gè)存儲(chǔ)庫(kù)粘合在一起,則子模塊和子樹(shù)合并是錯(cuò)誤的工具,因?yàn)樗鼈儾粫?huì)保留所有文件歷史記錄(正如其他評(píng)論者所指出的那樣)。請(qǐng)參閱stackoverflow.com/questions/13040958/…。

答3:

huntsbot.com精選全球7大洲遠(yuǎn)程工作機(jī)會(huì),涵蓋各領(lǐng)域,幫助想要遠(yuǎn)程工作的數(shù)字游民們能更精準(zhǔn)、更高效的找到對(duì)方。

另一個(gè)存儲(chǔ)庫(kù)的單個(gè)分支可以很容易地放置在保留其歷史記錄的子目錄下。例如:

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

這將顯示為單個(gè)提交,其中 Rails 主分支的所有文件都添加到“rails”目錄中。然而,提交的標(biāo)題包含對(duì)舊歷史樹(shù)的引用:

從提交 添加’rails/’

其中 是 SHA-1 提交哈希。你仍然可以看到歷史,責(zé)怪一些變化。

git log 
git blame  -- README.md

請(qǐng)注意,您無(wú)法從此處看到目錄前綴,因?yàn)檫@是一個(gè)完好無(wú)損的實(shí)際舊分支。您應(yīng)該將其視為通常的文件移動(dòng)提交:到達(dá)它時(shí)您將需要額外的跳轉(zhuǎn)。

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

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

有更復(fù)雜的解決方案,例如手動(dòng)執(zhí)行此操作或重寫(xiě)其他答案中描述的歷史記錄。

git-subtree 命令是官方 git-contrib 的一部分,一些數(shù)據(jù)包管理器默認(rèn)安裝它(OS X Homebrew)。但是除了 git 之外,您可能還必須自己安裝它。

以下是有關(guān)如何安裝 Git SubTree 的說(shuō)明(截至 2013 年 6 月):stackoverflow.com/a/11613541/694469(我將 git co v1.7.11.3 替換為 ... v1.8.3)。

感謝您對(duì)以下答案的提醒。截至 git 1.8.4 'subtree' 仍然不包括在內(nèi)(至少不在 Ubuntu 12.04 git ppa (ppa:git-core/ppa) 上)

我可以確認(rèn),在此之后,git log rails/somefile 將不會(huì)顯示該文件的提交歷史記錄,但合并提交除外。正如@artfulrobot 建議的那樣,檢查 Greg Hewgill's answer。您可能需要在要包含的存儲(chǔ)庫(kù)上使用 git filter-branch。

或者閱讀 Eric Lee 的“將兩個(gè) Git 存儲(chǔ)庫(kù)合并到一個(gè)存儲(chǔ)庫(kù)而不丟失文件歷史記錄”saintgimp.org/2013/01/22/…

正如其他人所說(shuō),git subtree 可能不會(huì)像您想的那樣!有關(guān)更完整的解決方案,請(qǐng)參閱 here。

答4:

huntsbot.com全球7大洲遠(yuǎn)程工作機(jī)會(huì),探索不一樣的工作方式

如果您想單獨(dú)維護(hù)項(xiàng)目,則子模塊方法很好。但是,如果您真的想將兩個(gè)項(xiàng)目合并到同一個(gè)存儲(chǔ)庫(kù)中,那么您還有更多工作要做。

首先是使用 git filter-branch 將第二個(gè)存儲(chǔ)庫(kù)中所有內(nèi)容的名稱重寫(xiě)為您希望它們結(jié)束的子目錄中。因此,您將擁有 projb/foo.c 和 projb/bar.html,而不是 foo.c、bar.html。

然后,您應(yīng)該能夠執(zhí)行以下操作:

git remote add projb [wherever]
git pull projb

git pull 將執(zhí)行 git fetch,然后執(zhí)行 git merge。如果您要拉入的存儲(chǔ)庫(kù)還沒(méi)有 projb/ 目錄,則應(yīng)該沒(méi)有沖突。

進(jìn)一步搜索表明進(jìn)行了類似的操作以將 gitk 合并到 git。 Junio C Hamano 在這里寫(xiě)到:http://www.mail-archive.com/git@vger.kernel.org/msg03395.html

子樹(shù)合并將是更好的解決方案,并且不需要重寫(xiě)包含項(xiàng)目的歷史記錄

我想知道如何使用 git filter-branch 來(lái)實(shí)現(xiàn)這一點(diǎn)。在手冊(cè)頁(yè)中它說(shuō)的是相反的方式:使 subdir/ 成為根,但不是相反。

如果它解釋了如何使用 filter-branch 來(lái)達(dá)到預(yù)期的結(jié)果,這個(gè)答案會(huì)很棒

我在這里找到了如何使用過(guò)濾器分支:stackoverflow.com/questions/4042816/…

有關(guān) Greg 大綱的實(shí)施,請(qǐng)參見(jiàn) this answer。

答5:

huntsbot.com提供全網(wǎng)獨(dú)家一站式外包任務(wù)、遠(yuǎn)程工作、創(chuàng)意產(chǎn)品分享與訂閱服務(wù)!

git-subtree 不錯(cuò),但可能不是您想要的。

例如,如果 projectA 是在 B 中創(chuàng)建的目錄,則在 git subtree 之后,

git log projectA

僅列出一個(gè)提交:合并。合并項(xiàng)目的提交用于不同的路徑,因此它們不會(huì)顯示。

Greg Hewgill 的答案最接近,盡管它實(shí)際上并沒(méi)有說(shuō)明如何重寫(xiě)路徑。

解決方案非常簡(jiǎn)單。

(1) 在 A 中,

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

注意:這會(huì)改寫(xiě)歷史;您可能需要先備份 A。

注意:如果您在文件名或路徑中使用非 ascii 字符(或白色字符),則必須修改 sed 命令中的替換腳本。在這種情況下,由“l(fā)s-files -s”生成的記錄中的文件位置以引號(hào)開(kāi)頭。

(2) 然后在 B 中運(yùn)行

git pull path/to/A

瞧!您在 B 中有一個(gè) projectA 目錄。如果您運(yùn)行 git log projectA,您將看到來(lái)自 A 的所有提交。

在我的例子中,我想要兩個(gè)子目錄,projectA 和 projectB。在這種情況下,我也對(duì) B 執(zhí)行了步驟 (1)。

您似乎從 stackoverflow.com/a/618113/586086 復(fù)制了您的答案?

@AndrewMao,我想是的......我實(shí)際上不記得了。這個(gè)腳本我用過(guò)不少。

我要補(bǔ)充一點(diǎn) \t 在 OS X 上不起作用,你必須輸入

"$GIT_INDEX_FILE" 必須被引用(兩次),否則如果路徑包含空格,您的方法將失敗。

如果你想知道,插入一個(gè) 在 osx 中,您需要 Ctrl-V

答6:

huntsbot.com洞察每一個(gè)產(chǎn)品背后的需求與收益,從而捕獲靈感

如果兩個(gè)存儲(chǔ)庫(kù)具有相同類型的文件(例如不同項(xiàng)目的兩個(gè) Rails 存儲(chǔ)庫(kù)),您可以將輔助存儲(chǔ)庫(kù)的數(shù)據(jù)獲取到當(dāng)前存儲(chǔ)庫(kù):

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

然后將其合并到當(dāng)前存儲(chǔ)庫(kù):

git merge --allow-unrelated-histories branch_name

如果您的 Git 版本小于 2.9,請(qǐng)刪除 --allow-unrelated-histories。

在此之后,可能會(huì)發(fā)生沖突。例如,您可以使用 git mergetool 解決它們。 kdiff3 可以單獨(dú)與鍵盤(pán)一起使用,因此讀取代碼時(shí)只需幾分鐘就需要 5 個(gè)沖突文件。

記得完成合并:

git commit

我喜歡這個(gè)解決方案的簡(jiǎn)單性,它看起來(lái)就像我正在尋找的東西,但它基本上不等同于 git pull --allow-unrelated-histories 嗎?

@Prometheus 有點(diǎn)像。我現(xiàn)在沒(méi)有測(cè)試它,但可能 pull 需要將遠(yuǎn)程存儲(chǔ)庫(kù)添加為真正的遠(yuǎn)程,這只會(huì)將必要的內(nèi)容獲取到分支并合并該內(nèi)容。

答7:

huntsbot.com提供全網(wǎng)獨(dú)家一站式外包任務(wù)、遠(yuǎn)程工作、創(chuàng)意產(chǎn)品分享與訂閱服務(wù)!

在使用合并時(shí),我一直在丟失歷史記錄,所以我最終使用了 rebase,因?yàn)樵谖业那闆r下,兩個(gè)存儲(chǔ)庫(kù)不同,以至于不會(huì)在每次提交時(shí)合并:

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

=> 解決沖突,然后繼續(xù),根據(jù)需要多次…

git rebase --continue

這樣做會(huì)導(dǎo)致一個(gè)項(xiàng)目擁有來(lái)自 projA 的所有提交,然后是來(lái)自 projB 的提交

答8:

打造屬于自己的副業(yè),開(kāi)啟自由職業(yè)之旅,從huntsbot.com開(kāi)始!

在我的例子中,我有一個(gè) my-plugin 存儲(chǔ)庫(kù)和一個(gè) main-project 存儲(chǔ)庫(kù),我想假設(shè) my-plugin 一直是在 main-project 的 plugins 子目錄中開(kāi)發(fā)的。

基本上,我重寫(xiě)了 my-plugin 存儲(chǔ)庫(kù)的歷史,以便所有開(kāi)發(fā)都發(fā)生在 plugins/my-plugin 子目錄中。然后,我將 my-plugin 的發(fā)展歷史添加到 main-project 歷史中,并將兩棵樹(shù)合并在一起。由于 main-project 存儲(chǔ)庫(kù)中沒(méi)有 plugins/my-plugin 目錄,因此這是一個(gè)簡(jiǎn)單的無(wú)沖突合并。生成的存儲(chǔ)庫(kù)包含兩個(gè)原始項(xiàng)目的所有歷史記錄,并且有兩個(gè)根源。

TL;博士

$ 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

長(zhǎng)版

首先,創(chuàng)建 my-plugin 存儲(chǔ)庫(kù)的副本,因?yàn)槲覀儗⒅貙?xiě)此存儲(chǔ)庫(kù)的歷史記錄。

現(xiàn)在,導(dǎo)航到 my-plugin 存儲(chǔ)庫(kù)的根目錄,檢查您的主分支(可能是 master),然后運(yùn)行以下命令。當(dāng)然,無(wú)論您的實(shí)際姓名是什么,您都應(yīng)該替換 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

現(xiàn)在解釋一下。 git filter-branch --tree-filter (…) HEAD 對(duì)可從 HEAD 訪問(wèn)的每個(gè)提交運(yùn)行 (…) 命令。請(qǐng)注意,這直接對(duì)每次提交存儲(chǔ)的數(shù)據(jù)進(jìn)行操作,因此我們不必?fù)?dān)心“工作目錄”、“索引”、“暫存”等概念。

如果您運(yùn)行的 filter-branch 命令失敗,它會(huì)在 .git 目錄中留下一些文件,并且下次嘗試 filter-branch 時(shí)它會(huì)抱怨此問(wèn)題,除非您向 filter-branch 提供 -f 選項(xiàng).

至于實(shí)際的命令,我沒(méi)有讓 bash 做我想做的事,所以我使用 zsh -c 讓 zsh 執(zhí)行命令。首先,我設(shè)置了 extended_glob 選項(xiàng),它啟用了 mv 命令中的 ^(…) 語(yǔ)法,以及 glob_dots 選項(xiàng),它允許我選擇帶有 glob 的點(diǎn)文件(例如 .gitignore) (^(…))。

接下來(lái),我使用 mkdir -p 命令同時(shí)創(chuàng)建 plugins 和 plugins/my-plugin。

最后,我使用 zsh“負(fù) glob”功能 ^(.git|plugins) 來(lái)匹配存儲(chǔ)庫(kù)根目錄中除 .git 和新創(chuàng)建的 my-plugin 文件夾之外的所有文件。 (此處可能不需要排除 .git,但嘗試將目錄移動(dòng)到自身是錯(cuò)誤的。)

在我的存儲(chǔ)庫(kù)中,初始提交不包含任何文件,因此 mv 命令在初始提交時(shí)返回錯(cuò)誤(因?yàn)闆](méi)有可移動(dòng)的內(nèi)容)。因此,我添加了一個(gè) || true,以便 git filter-branch 不會(huì)中止。

–all 選項(xiàng)告訴 filter-branch 重寫(xiě)存儲(chǔ)庫(kù)中 所有 分支的歷史記錄,并且需要額外的 – 告訴 git 將其解釋為選項(xiàng)列表的一部分用于重寫(xiě)分支,而不是作為 filter-branch 本身的選項(xiàng)。

現(xiàn)在,導(dǎo)航到您的 main-project 存儲(chǔ)庫(kù)并檢查您想要合并到的任何分支。添加 my-plugin 存儲(chǔ)庫(kù)的本地副本(修改其歷史)作為 main-project 的遠(yuǎn)程:

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

現(xiàn)在,您的提交歷史中將有兩個(gè)不相關(guān)的樹(shù),您可以使用以下方法很好地可視化它們:

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

要合并它們,請(qǐng)使用:

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

請(qǐng)注意,在 2.9.0 之前的 Git 中,–allow-unrelated-histories 選項(xiàng)不存在。如果您使用的是這些版本之一,只需省略該選項(xiàng):–allow-unrelated-histories 阻止的錯(cuò)誤消息也被添加到 2.9.0 中。

您不應(yīng)該有任何合并沖突。如果這樣做,則可能意味著 filter-branch 命令無(wú)法正常工作,或者 main-project 中已經(jīng)存在 plugins/my-plugin 目錄。

確保為任何未來(lái)的貢獻(xiàn)者輸入一個(gè)解釋性的提交消息,他們想知道黑客正在做什么來(lái)創(chuàng)建一個(gè)有兩個(gè)根的存儲(chǔ)庫(kù)。

您可以使用上面的 git log 命令可視化新的提交圖,它應(yīng)該有兩個(gè)根提交。請(qǐng)注意,只會(huì)合并 master 分支。這意味著,如果您在其他 my-plugin 分支上有重要的工作要合并到 main-project 樹(shù)中,則在完成這些合并之前,您應(yīng)該避免刪除 my-plugin 遠(yuǎn)程。如果您不這樣做,那么來(lái)自這些分支的提交仍將位于 main-project 存儲(chǔ)庫(kù)中,但有些將無(wú)法訪問(wèn)并且容易受到最終垃圾收集的影響。 (此外,您必須通過(guò) SHA 引用它們,因?yàn)閯h除遠(yuǎn)程會(huì)刪除其遠(yuǎn)程跟蹤分支。)

或者,在您合并所有要保留在 my-plugin 中的內(nèi)容后,您可以使用以下方法刪除 my-plugin 遠(yuǎn)程:

$ git remote remove my-plugin

您現(xiàn)在可以安全地刪除您更改了其歷史記錄的 my-plugin 存儲(chǔ)庫(kù)的副本。就我而言,在合并完成并推送后,我還在真正的 my-plugin 存儲(chǔ)庫(kù)中添加了棄用通知。

在帶有 git --version 2.9.0 和 zsh --version 5.2 的 Mac OS X El Capitan 上進(jìn)行了測(cè)試。你的旅費(fèi)可能會(huì)改變。

參考:

https://git-scm.com/docs/git-filter-branch

https://unix.stackexchange.com/questions/6393/how-do-you-move-all-files-include-hidden-from-one-directory-to-another

http://www.refining-linux.org/archives/37/ZSH-Gem-2-Extended-globbing-and-expansion/

從 Git 存儲(chǔ)庫(kù)清除文件失敗,無(wú)法創(chuàng)建新備份

git,所有分支上的過(guò)濾器分支

--allow-unrelated-histories 來(lái)自哪里?

@MarceloFilho 檢查 man git-merge。 默認(rèn)情況下,git merge 命令拒絕合并不共享共同祖先的歷史。當(dāng)合并兩個(gè)獨(dú)立開(kāi)始的項(xiàng)目的歷史時(shí),此選項(xiàng)可用于覆蓋此安全性。由于這種情況很少見(jiàn),因此默認(rèn)情況下不存在啟用此功能的配置變量,因此不會(huì)添加。

應(yīng)該在 git version 2.7.2.windows.1 上可用嗎?

@MarceloFilho 這是在 2.9.0 中添加的,但在舊版本中,您不必傳遞該選項(xiàng)(它會(huì)起作用)。 github.com/git/git/blob/…

這運(yùn)作良好。而且我能夠使用過(guò)濾器分支將文件名重寫(xiě)到合并之前樹(shù)中我想要的位置。我想如果您需要在主分支之外移動(dòng)歷史記錄,則需要做更多的工作。

答9:

打造屬于自己的副業(yè),開(kāi)啟自由職業(yè)之旅,從huntsbot.com開(kāi)始!

幾天來(lái)我一直在嘗試做同樣的事情,我使用的是 git 2.7.2。子樹(shù)不保留歷史。

如果您不再使用舊項(xiàng)目,您可以使用此方法。

我建議你先分支 B 并在分支中工作。

以下是沒(méi)有分支的步驟:

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  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 

git merge A/

mkdir A

# move all the files into subdir A, excluding .git
git mv  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

如果您現(xiàn)在在 subdir A 中記錄任何文件,您將獲得完整的歷史記錄

git log --follow A/

這是幫助我做到這一點(diǎn)的帖子:

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

答10:

huntsbot.com聚合了超過(guò)10+全球外包任務(wù)平臺(tái)的外包需求,尋找外包任務(wù)與機(jī)會(huì)變的簡(jiǎn)單與高效。

如果您想將 repo B 中的分支中的文件放在 repo A 的子樹(shù)中并保留歷史記錄,請(qǐng)繼續(xù)閱讀。 (在下面的示例中,我假設(shè)我們希望將 repo B 的 master 分支合并到 repo A 的 master 分支中。)

在 repo A 中,首先執(zhí)行以下操作以使 repo B 可用:

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

現(xiàn)在我們?cè)?repo A 中創(chuàng)建一個(gè)全新的分支(只有一個(gè)提交),我們稱之為 new_b_root。生成的提交將包含在 repo B 的主分支的第一次提交中提交的文件,但放在名為 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))"

說(shuō)明: checkout 命令的 --orphan 選項(xiàng)從 A 的主分支中簽出文件,但不創(chuàng)建任何提交。我們可以選擇任何提交,因?yàn)榻酉聛?lái)我們無(wú)論如何都會(huì)清除所有文件。然后,還沒(méi)有提交(-n),我們從 B 的主分支中挑選第一個(gè)提交。 (cherry-pick 保留了直接簽出似乎無(wú)法做到的原始提交消息。)然后我們創(chuàng)建子樹(shù),我們希望將所有文件從 repo B 中放入其中。然后我們必須移動(dòng)引入的所有文件櫻桃采摘到子樹(shù)。在上面的示例中,只有一個(gè) README 文件要移動(dòng)。然后我們提交我們的 B-repo 根提交,同時(shí),我們還保留原始提交的時(shí)間戳。

現(xiàn)在,我們將在新創(chuàng)建的 new_b_root 之上創(chuàng)建一個(gè)新的 B/master 分支。我們將新分支稱為 b:

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

現(xiàn)在,我們將 b 分支合并到 A/master:

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

最后,您可以刪除 B 遠(yuǎn)程和臨時(shí)分支:

git remote remove B
git branch -D new_b_root b

最終的圖形將具有如下結(jié)構(gòu):

https://i.stack.imgur.com/CB80G.png

很好的答案,謝謝!我真的錯(cuò)過(guò)了來(lái)自 Andresch Serj 的“git subtree”或“merge --allow-unrelated-histories”的其他答案,即子目錄沒(méi)有日志。

答11:

保持自己快人一步,享受全網(wǎng)獨(dú)家提供的一站式外包任務(wù)、遠(yuǎn)程工作、創(chuàng)意產(chǎn)品訂閱服務(wù)–huntsbot.com文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-493788.html

我在這里收集了很多關(guān)于 Stack OverFlow 等的信息,并設(shè)法將一個(gè)腳本放在一起,為我解決了這個(gè)問(wèn)題。

需要注意的是,它只考慮每個(gè)存儲(chǔ)庫(kù)的“開(kāi)發(fā)”分支,并將其合并到一個(gè)全新存儲(chǔ)庫(kù)中的單獨(dú)目錄中。

標(biāo)簽和其他分支被忽略 - 這可能不是你想要的。

該腳本甚至處理功能分支和標(biāo)簽 - 在新項(xiàng)目中重命名它們,以便您知道它們來(lái)自哪里。

#!/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  
## - where  is the name of the new project to create
## - and  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  "
  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 獲得它

首先創(chuàng)建一個(gè)包含每個(gè)存儲(chǔ)庫(kù)的 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

然后調(diào)用提供項(xiàng)目名稱和腳本路徑的腳本:

./mergeGitRepositories.sh eitchnet_test eitchnet.lst

腳本本身有很多注釋?xiě)?yīng)該解釋它的作用。

與其將讀者引導(dǎo)至答案,請(qǐng)?jiān)诖颂幇l(fā)布答案(也就是將您在該評(píng)論中所說(shuō)的內(nèi)容編輯到此答案中)。

當(dāng)然,只是認(rèn)為最好不要重復(fù)自己... =)

如果您認(rèn)為這個(gè)問(wèn)題與另一個(gè)問(wèn)題相同,那么您可以使用問(wèn)題本身下方的“標(biāo)記”鏈接將其標(biāo)記為重復(fù),并指出另一個(gè)問(wèn)題。如果它不是重復(fù)的問(wèn)題,但您認(rèn)為完全相同的答案可用于解決這兩個(gè)問(wèn)題,那么只需對(duì)這兩個(gè)問(wèn)題發(fā)布相同的答案(就像您現(xiàn)在所做的那樣)。感謝您的貢獻(xiàn)!

驚人!在 Windows bash 提示符下不起作用,但它完美地從運(yùn)行 ubuntu 的 Vagrant 盒子中運(yùn)行。多么節(jié)省時(shí)間!

舊的但是.. 用粗體(和/或更大的字體)警告可能是個(gè)好主意?

原文鏈接:https://www.huntsbot.com/qa/7Q53/how-do-you-merge-two-git-repositories?lang=zh_CN&from=csdn

保持自己快人一步,享受全網(wǎng)獨(dú)家提供的一站式外包任務(wù)、遠(yuǎn)程工作、創(chuàng)意產(chǎn)品訂閱服務(wù)–huntsbot.com

到了這里,關(guān)于如何合并兩個(gè) Git 存儲(chǔ)庫(kù)?的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包