简体   繁体   English

如何将提交从一个 Git 存储库复制到另一个?

[英]How to copy commits from one Git repo to another?

Last week I created a Github repo and forgot to select a license for the repo.上周我创建了一个 Github 存储库,但忘记为该存储库选择许可证。 Now there are already 3 large commits.现在已经有 3 个大型提交。

I have asked the 3 contributors if it is ok if I delete the repo and then create it again with the same name and this time selecting the license when creating the repo, and they were fine with that.我已经询问了 3 位贡献者是否可以删除存储库,然后使用相同的名称再次创建它,这次在创建存储库时选择许可证,他们对此很好。

Question问题

Is there a way I can get the commits into the new repo (this time the first commit is the LICENSE file) and still keep the commit meta info?有没有办法可以将提交提交到新的仓库中(这次第一个提交是 LICENSE 文件)并且仍然保留提交元信息?

Is there a way I have get the commits into new repo (this time the first commit is the LICENSE file) and still keep the commit meta info?有没有办法将提交提交到新的存储库中(这次第一次提交是许可证文件)并且仍然保留提交元信息?

Yes, by adding a remote and cherry-picking the commits on top of your first commit.是的,通过在第一次提交的基础上添加远程和挑选提交。

# add the old repo as a remote repository 
git remote add oldrepo https://github.com/path/to/oldrepo

# get the old repo commits
git remote update

# examine the whole tree
git log --all --oneline --graph --decorate

# copy (cherry-pick) the commits from the old repo into your new local one
git cherry-pick sha-of-commit-one
git cherry-pick sha-of-commit-two
git cherry-pick sha-of-commit-three

# check your local repo is correct
git log

# send your new tree (repo state) to github
git push origin master

# remove the now-unneeded reference to oldrepo
git remote remove oldrepo

The rest of this answer is if you still want to add the LICENSE to your previous repo.此答案的其余部分是您是否仍想将 LICENSE 添加到之前的存储库中。

Yes.是的。 You can place your LICENSE commit as the first commit by rebasing.您可以通过变基将 LICENSE 提交作为第一次提交。

Rebasing is gits way of rearranging commit order while keeping all the commit authors and commit dates intact. Rebase 是一种重新排列提交顺序同时保持所有提交作者和提交日期完整的 git 方式。

When working on a shared repo, it's generally discouraged unless your entire team is git-fluent.在处理共享存储库时,通常不鼓励这样做,除非您的整个团队都精通 git。 For those that aren't, they can just clone a fresh copy of the repository.对于那些不是,他们可以克隆存储库的新副本。

Here's how you get your LICENSE commit as the first commit.以下是您如何将 LICENSE 提交作为第一次提交。

1. Update and rebase your local copy 1. 更新和rebase你的本地副本

Check out your project and place the LICENSE file in a commit ON TOP of your current 3 commit stack.检查您的项目并将 LICENSE 文件放在当前 3 个提交堆栈的顶部提交中。

#create LICENSE file, edit, add content, save
git add LICENSE
git commit -m 'Initial commit'

Then do an interactive rebase on the master branch to REARRANGE the commits.然后在 master 分支上进行交互式 rebase 以重新排列提交。

git rebase -i --root

It will open an editor.它将打开一个编辑器。 Move the bottom line (your "Initial commit" commit, the most recent commit) to the top of the file.将底线(您的“初始提交”提交,最近的提交)移至文件顶部。 Then save and quit the editor.然后保存并退出编辑器。

As soon as you exit the editor, git will write the commits in the order you just specified.只要您退出编辑器,git 就会按照您刚刚指定的顺序写入提交。

You now have your local copy of the repository updated.您现在已更新存储库的本地副本。 do:做:

git log

to verify.验证。

2. Force push your new repo state to github 2. 强制将你的新仓库状态推送到 github

Now that your copy is updated, you have to force push it to github.现在您的副本已更新,您必须强制将其推送到 github。

git push -f origin master

This will tell github to move the master branch to its new location.这将告诉 github 将主分支移动到新位置。 You should only force push in rare occasions like this where everybody working with it is aware of the pending change, else it will confuse your collaborators.你应该只在这种罕见的情况下强制推送,在这种情况下,使用它的每个人都知道挂起的更改,否则它会使你的合作者感到困惑。

3. Synchronize collaborators to github 3. 将协作者同步到 github

Lastly, all the collaborators will have to synchronize to this repository.最后,所有协作者都必须同步到此存储库。

First they must have clean repositories as the following command can be destructive if there are unsaved changes.首先,他们必须拥有干净的存储库,因为如果有未保存的更改,以下命令可能具有破坏性。

# make sure there are no unsaved changes
git status 

# pull the latest version from github
git fetch  

# move their master branch pointer to the one you published to github.
git reset --hard origin/master

That's it.而已。 Everybody should be in sync now.现在每个人都应该同步。

I had a similar problem where I forgot to fork a repo to my github and added several commits before I realized my mistake.我有一个类似的问题,在我意识到我的错误之前,我忘记将 repo 分叉到我的 github 并添加了几次提交。

I found a pretty simple solution.我找到了一个非常简单的解决方案。

First remove the remote to the original repo首先将遥控器删除到原始 repo

git remote remove origin

Second add a remote to the new fork on my github其次在我的 github 上的新叉中添加一个遥控器

git remote add origin <my repo URL>

Then I pushed to origin master and all of my commits showed up on my github.然后我推送到 origin master,我所有的提交都出现在我的 github 上。

  • Destination Git = UrlD (existing content doesn't matter)目标 Git = UrlD(现有内容无关紧要)
  • SourceGit = UrlS SourceGit = UrlS

     git clone UrlS git remote add origin2 UrlD git push -f origin2 master

Now the Destination will have the same data as Source(You can also use origin instead of origin2)现在 Destination 将具有与 Source 相同的数据(您也可以使用 origin 代替 origin2)

I used the following approach:我使用了以下方法:

  • Clone the source repo to a folder like /c/SrcRepo将源代码库克隆到 /c/SrcRepo 等文件夹

  • Clone the destination repo to a folder like /c/DstRepo and switch to the destination branch将目标仓库克隆到 /c/DstRepo 等文件夹并切换到目标分支

  • In the root folder of the destination repo run the command:在目标 repo 的根文件夹中运行命令:

    git pull /c/SrcRepo srcBranch --allow-unrelated-histories git pull /c/SrcRepo srcBranch --allow-unrelated-history

No necessary to create an additional remote reference无需创建额外的远程引用

Based on @Moocowmoo's answer but trying to streamline it bit more基于@Moocowmoo 的回答,但试图进一步简化它

What this does differently is tries to avoid conflicts as much as possible, just assuming that the remote is correct.这样做的不同之处在于尽可能地避免冲突,只是假设遥控器是正确的。

It doesn't however handle deleted files well, so there is still a manual element.但是它不能很好地处理已删除的文件,因此仍然有一个手动元素。

# assuming you are already on the branch you want to be
git remote add oldrepo https://github.com/path/to/oldrepo
git fetch oldrepo

# take all or subset of changes from a branch
git cherry-pick --strategy recursive --strategy-option theirs oldestCommitHash^..latestCommitHash

# or take all changes included in a specific merge commit (easiest)
git cherry-pick --strategy recursive --strategy-option theirs mergeCommitHash^..mergeCommitHash

# handling deleted files/unhandled conflicts
# just keep repeating this section
git mergetool
# either c/m or d based on if you want to keep or delete the files
git cherry-pick --continue

In my case I needed to find out differences between the old and new repos.就我而言,我需要找出新旧存储库之间的差异。 So in the new repo added the old one.所以在新的回购中添加了旧的。

git remote add old https://gitlab.site.az/old-blog.git

Fetch all remotes获取所有遥控器

git fetch --all

Find different commits查找不同的提交

git log --graph --oneline --pretty=format:"%h%x09%an%x09%ad%x09%s" --abbrev-commit --date=relative develop..old/develop

Get commits you selected获取您选择的提交

git cherry-pick SHA1 SHA2 SHA4

this worked better for me:这对我来说效果更好:

git remote add oldrepo https://github.com/path/to/oldrepo
git remote update
git merge --squash --allow-unrelated-histories <commit-hash>
git push origin main

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM