Похоже, что pip сделал рефакторинг и переместил main на внутренний. Существует всестороннее обсуждение этого вопроса: https://github.com/pypa/pip/issues/5240
Обходной путь для меня состоял в том, чтобы изменить
import pip
pip.main(...)
to
from pip._internal import main
main(...)
Я рекомендую прочитать обсуждение, я не уверен, что это лучший подход, но он работал для моих целей.
Единственная ветвь другого репозитория может быть легко помещена под подкаталог, сохраняющий свою историю. Например:
git subtree add --prefix=rails git://github.com/rails/rails.git master
Это будет отображаться как одно комманда, где все файлы главной ветки Rails добавляются в каталог «rails». Однако заголовок commit содержит ссылку на старое дерево истории:
Добавить 'rails /' из commit
blockquote><rev>
Где
<rev>
является SHA-1 фиксирует хэш. Вы все еще можете увидеть историю, вините некоторые изменения.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-contrib, некоторые менеджеры пакетов устанавливают его по умолчанию (OS X Homebrew). Но вам, возможно, придется установить его самостоятельно в дополнение к git.
Вот два возможных решения:
Либо копировать репозиторий A в отдельный каталог в более крупном проекте B, либо (возможно, лучше) клонировать репозиторий A в подкаталог в проекте B. Затем используйте git submodule , чтобы сделать этот репозиторий субмодулем репозитория B.
Это хорошее решение для слабосвязанных репозиториев, где разработка в репозитории A продолжается, и основная часть разработки - отдельная автономная разработка в A. См. также SubmoduleSupport и GitSubmoduleTutorial страницы в Git Wiki.
Вы можете объединить репозиторий A в подкаталог проекта B, используя стратегию слияния поддерева . Это описано в Subtree Merging и You Markus Prinz.
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 требуется опция --allow-unrelated-histories
.)
Или вы можете использовать инструмент поддерева git ( репозиторий на GitHub ) от apenwarr (Avery Pennarun), анонсированный, например, в его сообщении в блоге . Новая альтернатива подмодулям Git: git subtree .
Я думаю, что в вашем случае (A должен быть частью более крупного проекта B) правильным решением было бы использовать слияние поддерева .
Если вы хотите объединить project-a
в project-b
:
cd path/to/project-b
git remote add project-a path/to/project-a
git fetch project-a
git merge --allow-unrelated-histories project-a/master # or whichever branch you want to merge
git remote remove project-a
Взято из: git слить разные репозитории?
Этот метод работал очень хорошо для меня, он короче и, на мой взгляд, намного чище.
Примечание: Параметр --allow-unrelated-histories
существует только с git> = 2.9. См. Git-git merge Документация / -allow-unrelated-history
Эта функция будет клонировать удаленное репо в локальный репозиторий, после того, как слияние всех коммитов будет сохранено, 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="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-histories
существует только тогда, когда git> = 2.9.
Я продолжал проигрывать историю при использовании слияния, поэтому в итоге я использовал rebase, поскольку в моем случае два репозитория достаточно различны, чтобы не сливаться при каждой фиксации:
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
Выполнение этого приводит к одному проекту, все из которого совершаются с projA, за которым следуют коммиты из projB
Я объединять проекты немного вручную, что позволяет мне избежать необходимости иметь дело с конфликтами слияния.
сначала скопировать файлы из другого проекта, но вы хотите их.
cp -R myotherproject newdirectory
git add newdirectory
next pull in history
git fetch path_or_url_to_other_repo
tell git, чтобы объединиться в истории последней извлеченной вещи
echo 'FETCH_HEAD' > .git/MERGE_HEAD
теперь зафиксировать, однако вы обычно совершаете
git commit
Если вы пытаетесь просто склеить два репозитория вместе, подмодули и слияния поддеревьев являются неправильным инструментом для использования, потому что они не сохраняют всю историю файлов (как люди отметили другие ответы). См. Этот ответ здесь для простого и правильного способа сделать это.
git-subtree
хорош, но, вероятно, это не тот, который вам нужен.
Например, если projectA
является каталогом, созданным в B, после git subtree
,
git log projectA
перечисляет только одно сообщение: слияние. Коммиты из объединенного проекта предназначены для разных путей, поэтому они не отображаются.
Ответ Greg Hewgill близок, хотя на самом деле он не говорит, как переписать пути.
< hr>Решение на удивление просто.
(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
Примечание: Это перезаписывает историю, поэтому, если вы намереваетесь продолжать использовать это репо A, вы можете сначала клонировать (копировать) его исходную копию.
(2) Затем в B запустите
git pull path/to/A
Voila! У вас есть каталог projectA
в B. Если вы запустите git log projectA
, вы увидите все коммиты с A.
В моем случае мне нужны два подкаталога: projectA
и projectB
. В этом случае я также сделал шаг (1) на B.
У меня была аналогичная задача, но в моем случае мы разработали одну версию кодовой базы в репо A, а затем клонировали ее в новый репо-репо B для новой версии продукта. После исправления некоторых ошибок в репо A нам нужно было FI внести изменения в репо B. Закончилось выполнение следующего:
Работала с удовольствием :)
Данная команда - наилучшее возможное решение, которое я предлагаю.
git subtree add --prefix=MY_PROJECT git://github.com/project/my_project.git master
Если вы хотите поместить файлы из ветки в репо B в поддереве репо A и , также сохраните историю, продолжайте чтение. (В приведенном ниже примере я предполагаю, что мы хотим, чтобы главная ветвь репо B была объединена с главной ветвью репо A.)
В репо A сначала сделайте следующее, чтобы сделать репо B доступным:
git remote add B ../B # Add repo B as a new remote.
git fetch B
Теперь мы создаем совершенно новую ветвь (только с одной фиксацией) в репо А, которую мы называем new_b_root
. Результирующая фиксация будет иметь файлы, которые были зафиксированы в первой фиксации главной ветви репо 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))"
Объяснение: Параметр --orphan
для команды проверки проверяет файлы из главной ветви А, но не создает никаких фиксаций. Мы могли бы выбрать любую фиксацию, потому что в дальнейшем мы все равно очищаем все файлы. Затем, не совершая пока (-n
), мы выбираем первую фиксацию из главной ветви B. (Вишневый диск сохраняет исходное сообщение фиксации, которое, как представляется, не делает прямую проверку). Затем мы создаем поддерево, где мы хотим поместить все файлы из репо B. Затем нам нужно переместить все файлы, которые были введены в вишневый выбор в поддерево. В приведенном выше примере есть только файл README
для перемещения. Затем мы фиксируем фиксацию корня B-repo и в то же время сохраняем временную метку исходного коммита.
Теперь мы создадим новую ветвь 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 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
Я знаю, что это уже давно, но я не был доволен другими ответами, которые я нашел здесь, поэтому я написал это:
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 репозиториев
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
Если вы хотите объединить три или более проектов в одном коммите, выполните действия, описанные в других ответах (remote add -f
, merge
). Затем (мягкий) сбросьте индекс на старую голову (где не произошло слияния). Добавьте все файлы (git add -A
) и скопируйте их (сообщение «Объединение проектов A, B, C и D в один проект). Теперь это идентификатор commit.
Теперь создайте .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
. Не всегда добавляйте это, потому что это может привести к перезаписи некоторых коммитов. Подробнее см. В странице man filter-branch , найдите «трансплантаты».
Теперь, ваш последний commit имеет соответствующих родителей.
Я собрал много информации здесь о Stack & nbsp; OverFlow и т. д., и мне удалось собрать сценарий вместе, который решает проблему для меня.
Оговорка в том, что она учитывает только «развить» ветвь каждого репозитория и слить его в отдельный каталог в совершенно новом репозитории.
Теги и другие ветви игнорируются - это может быть не то, что вы хотите.
Скрипт даже обрабатывает ветки и теги функций - переименование их в новом проекте, чтобы вы знали, откуда они пришли.
#!/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 containing the URLs to the repositories
## which are to be merged on separate lines.
##
## Author: Robert von Burg
## eitch@eitchnet.ch
##
## Version: 0.2.0
## Created: 2015-06-17
##
################################################################################
#
# Disallow using undefined variables
shopt -s -o nounset
# Script variables
declare SCRIPT_NAME="${0##*/}"
declare SCRIPT_DIR="$(cd ${0%/*} ; pwd)"
declare ROOT_DIR="$PWD"
# Detect proper usage
if [ "$#" -ne "2" ] ; then
echo -e "ERROR: Usage: $0 <new_project> <my_repo_urls.lst>"
exit 1
fi
# Script functions
function failed() {
echo -e "ERROR: Merging of projects failed:"
echo -e "$1"
exit 1
}
function commit_merge() {
current_branch="$(git symbolic-ref HEAD 2>/dev/null)"
CHANGES=$(git status | grep "working directory clean")
MERGING=$(git status | grep "merging")
if [[ "$CHANGES" != "" ]] && [[ "$MERGING" == "" ]] ; then
echo -e "INFO: No commit required."
else
echo -e "INFO: Committing ${sub_project}..."
if ! git commit --quiet -m "[Project] Merged branch '$1' of ${sub_project}" ; then
failed "Failed to commit merge of branch '$1' of ${sub_project} into ${current_branch}"
fi
fi
}
## Script variables
PROJECT_NAME="${1}"
PROJECT_PATH="${ROOT_DIR}/${PROJECT_NAME}"
REPO_FILE="${2}"
REPO_URL_FILE="${ROOT_DIR}/${REPO_FILE}"
# 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: Creating new git repository ${PROJECT_NAME}..."
echo -e "===================================================="
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 th branches of this project
echo -e "INFO: Merging projects into new repository..."
echo -e "===================================================="
for url in $(cat ${REPO_URL_FILE}) ; do
# Extract the name of this project
export sub_project=${url##*/}
sub_project=${sub_project%*.git}
echo -e "INFO: Project ${sub_project}"
echo -e "----------------------------------------------------"
# Fetch the project
echo -e "INFO: Fetching ${sub_project}..."
git remote add "${sub_project}" "${url}"
if ! git fetch --no-tags --quiet ${sub_project} 2>/dev/null ; then
failed "Failed to fetch project ${sub_project}"
fi
# Add remote branches
echo -e "INFO: Creating local branches for ${sub_project}..."
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}..."
# Create and checkout new merge branch off of master
git checkout --quiet -b "${sub_project}/${branch_name}" master
git reset --hard --quiet
git clean -d --force --quiet
# Merge the project
echo -e "INFO: Merging ${sub_project}..."
if ! git merge --quiet --no-commit "remotes/${sub_project}/${branch_name}" 2>/dev/null ; 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."
else
echo -e "INFO: Moving files in branch ${branch_name} of ${sub_project} so we have a single directory..."
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" 2>/dev/null ; then
failed "sub_project ${sub_project} is missing master branch!"
fi
# Copy remote tags
echo -e "INFO: Copying tags for ${sub_project}..."
while read tag ; do
tag_ref=$(echo $tag | tr " " "\t" | cut -f 1)
tag_name=$(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%%^*}"
tag_new_name="${sub_project}/${tag_name}"
echo -e "INFO: Copying tag ${tag_name} to ${tag_new_name} for ref ${tag_ref}..."
if ! git tag "${tag_new_name}" "${tag_ref}" 2>/dev/null ; then
echo -e "WARN: Could not copy tag ${tag_name} to ${tag_new_name} for ref ${tag_ref}"
fi
done < <(git ls-remote --tags ${sub_project})
# Remove the remote to the old project
echo -e "INFO: Removing remote ${sub_project}..."
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 "===================================================="
for url in $(cat ${REPO_URL_FILE}) ; do
# extract the name of this project
export sub_project=${url##*/}
sub_project=${sub_project%*.git}
echo -e "INFO: Merging ${sub_project}..."
if ! git merge --quiet --no-commit "${sub_project}/master" 2>/dev/null ; 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
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
В самом скрипте есть много комментариев, которые должны объяснить, что он делает.
Я пытался делать то же самое в течение нескольких дней, я использую git 2.7.2. Subtree не сохраняет историю.
Вы можете использовать этот метод, если вы не будете использовать старый проект еще раз.
Я бы предположил, что сначала вы введете 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
Если вы сейчас регистрируете любой из файлов в subdir A, вы получите полную историю
git log --follow A/<file>
Это сообщение, помогите мне сделать это:
Если оба репозитория имеют одинаковые файлы (например, два репозитория Rails для разных проектов), вы можете получить данные вторичного репозитория в свой текущий репозиторий:
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
Подобно @Smar, но использует пути файловой системы, заданные в PRIMARY и SECONDARY:
PRIMARY=~/Code/project1
SECONDARY=~/Code/project2
cd $PRIMARY
git remote add test $SECONDARY && git fetch test
git merge test/master
Затем вы вручную объединяетесь.
(адаптировано из сообщения Anar Манафы )
Слить A внутри B:
1) В проекте A
git fast-export --all --date-order > /tmp/ProjectAExport
2) В проекте B
git checkout -b projectA
git fast-import --force < /tmp/ProjectAExport
В эта ветка выполняет все операции, которые вам нужно выполнить и совершать их.
C) Затем вернитесь к мастеру и классическому объединению между двумя ветвями:
git checkout master
git merge projectA