我会手动轻微合并项目,这样我就避免了需要处理合并冲突的情况。
首先,以任何你想要的方式复制其他项目中的文件。
cp -R myotherproject newdirectory
git add newdirectory
历史中的下一次拉取
git fetch path_or_url_to_other_repo
告诉Git合并上次获取的历史记录。
echo 'FETCH_HEAD' > .git/MERGE_HEAD
现在您可以按照通常的方式提交代码。
git commit
今天我遇到了以下问题,需要解决:
项目A位于Bitbucket上,项目B位于Code Commit上,它们是相同的项目,但是需要将A中的更改合并到B中。(关键是在项目A中创建与项目B中相同名称的分支)
这个函数会将远程仓库克隆到本地仓库目录,合并后所有提交记录将被保存,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。
给出的命令是我建议的最佳解决方案。
git subtree add --prefix=MY_PROJECT git://github.com/project/my_project.git master
remote add -> fetch -> merge策略的所有答案之外:如果您想保留来自其他存储库的标记,但不想将它们全部溢出到公共命名空间中(可能会发生冲突),您可能需要稍微更改fetch命令:
git fetch --no-tags other_repo
git fetch --no-tags other_repo 'refs/tags/*:refs/tags/other_repo/*'
第一个命令像往常一样获取所有的分支,但省略了附加到提交的标签,第二个命令也省略了通常的标签获取机制(有关更多信息,请参见git help fetch),并使用git的refspec功能将所有标记从X映射到other_repo/X。
引用(分支、标签)只是git中的文件,您可以使用目录进行命名空间。上述两个命令将保留来自第一个存储库的标记,而来自第二个存储库的标记将以other_repo/为前缀。
操作后最好删除其他远程仓库,以免意外地以正常方式获取标签并造成混乱。
我想将一个小项目移动到一个大项目的子目录中。由于我的小项目没有太多的提交,所以我使用了git format-patch --output-directory /path/to/patch-dir。然后在大项目中,我使用了git am --directory=dir/in/project /path/to/patch-dir/*。
这种方法比filter-branch要简单得多,也更加干净。当然,它可能并不适用于所有情况。
cd /path/to/project-a
git lfs fetch --all # some old LFS objects might only be on the server of project-a and not in your clone of project-a
# possible alternative to the following two commands (untested): do a git lfs fetch from path/to/project-b
git remote add project-b-origin url-to-project-b-server
git lfs push --all project-b-origin
在我的情况下,这解决了我在项目-a克隆目录中尝试git push合并结果时遇到的错误。
remote: GitLab: LFS objects are missing. Ensure LFS is properly set up or try a manual "git lfs push --all".
并且
Unable to find source for object <hash> (try running `git lfs fetch --all`)
Git LFS upload failed:
(missing) <path> (<hash>)