是否可以从另一个git存储库中挑选提交?


724

我正在使用一个git存储库,该存储库需要来自另一个不了解任何内容的git存储库的提交。

通常,我会HEAD@{x}在reflog中使用来进行选择,但是由于对此.gitreflog条目(不同的物理目录)一无所知,我该如何选择它?

我正在使用git-svn。我的第一个分支使用git-svntrunk一个颠覆回购,而下一个分支是在git-svn上一个Subversion分支。


2
这就是本·李Ben Lee)在这个问题上悬赏的原因:“我将悬赏奖励给正确的答案,而不是被接受的答案。我只需要等待24小时即可。” 但是,我不知道其中哪个应该是“正确答案”,以及为什么接受的答案不是“正确”。

1
目前尚不清楚问题的本质是什么。这些不同的回购协议有什么关联(如果有的话)?一个是另一个的叉子吗?还是他们实际上是两个完全独立且无关的项目?

@Cupcake,接受的答案很好,并且显然对OP有所帮助,因此应该接受。我所说的“正确”实际上只是“对我合适”(并根据评论,对其他几个人也是如此)。我只是认为我给予赏金的那个人应该得到与被接受的答案一样多的代表。
本李

Answers:


554

您需要将另一个存储库添加为远程存储库,然后获取其更改。从那里您可以看到提交,并且可以对其进行挑选。

像那样:

git remote add other https://example.link/repository.git
git fetch other

现在,您拥有所有要做的信息git cherry-pick

有关在此处使用遥控器的更多信息:https : //git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes


1
如果我使用git-svn怎么办?我的第一个分支使用主干的git-svn,下一个分支使用git-svn(感谢快速答复)
gitcoder182

1
首次克隆Subversion存储库时,请确保克隆整个存储库,而不只是主干。--stdlayout如果在Subversion中使用标准的主干/分支/标签布局,还请确保使用git-svn选项。那么Subversion分支将仅仅是一个远程git分支。
wilhelmtell

33
如果您使用的是Github,则可以通过将.patch附加到提交URL并使用来应用,以提取补丁git am < d821j8djd2dj812.patch。在GH之外,可以按照以下替代答案中的说明进行类似的操作。
拉迪肯德(Radicand)

2
@radicand以下哪个答案是“替代”一个?请链接到它。

7
从另一个存储库中挑选樱桃的详细步骤:coderwall.com/p/sgpksw/git-cherry-pick-from-other-repository
T. Kim Nguyen

854

给出的答案是使用format-patch,但是由于问题是如何从另一个文件夹中挑选,下面是一段代码来做到这一点:

$ git --git-dir=../<some_other_repo>/.git \
format-patch -k -1 --stdout <commit SHA> | \
git am -3 -k

(来自@cong ma的解释)

git format-patch命令some_other_repo从其SHA指定的提交中创建补丁(仅-1用于一次提交)。该修补程序通过管道传输到git am,该修补程序在本地应用该修补程序(这-3意味着如果该修补程序无法干净地应用,请尝试三路合并)。希望能解释。


18
这是可以发现的,但是如果有人可以对此进行扩展,那将是很棒的-确切地细分正在发生的事情(尤其是那些标志)将非常有用。
尼克F

45
@NickF,该git format-patch命令some_other_repo根据其SHA指定的提交(仅-1用于一次提交)创建补丁。该修补程序通过管道传输到git am,该修补程序在本地应用该修补程序(这-3意味着如果该修补程序无法干净地应用,请尝试三路合并)。希望能解释。
聪马

3
错误:修补程序失败:somefile.cs:85错误:somefile.cs:修补程序不适用您是否手动编辑了修补程序?它不适用于其索引中记录的Blob。无法退回到三路合并。修补程序在0001添加了GUI部件失败。在以下位置找到失败的修补程序的副本:<some_other_repo> /。git / rebase-apply / patch解决此问题后,运行“ git am --continue”。如果您希望跳过此补丁,请运行“ git am --skip”。要恢复原始分支并停止修补,请运行“ git am --abort”。
汤姆(Tom)

8
@Tom尝试使用--ignore-whitespace。完整命令: git --git-dir=../<some_other_repo>/.git format-patch -k -1 --stdout <commit SHA> | git am -3 -k --ignore-whitespace
杰克·格雷厄姆·阿诺德

7
@BoomShadow因为它更简单。添加远程和获取会带来其他所有回购的更改。此命令行是一次性操作。
乔纳森·莱因哈特

151

这是远程获取合并的示例。

cd /home/you/projectA
git remote add projectB /home/you/projectB
git fetch projectB

那么你也能:

git cherry-pick <first_commit>..<last_commit>

或者你甚至可以合并整个分支

git merge projectB/master

54
git merge projectB/master 是非常,非常错误的,因为你没有应用从单一的更改提交(如摘樱桃会),你实际上是在合并的所有变化projectB/master未包含在自己的master分公司。

4
我认为这是原始海报的意图。否则,是的,这不是他们的正确选择。
布莱恩

5
当两个存储库相关联时,这非常有用。
罗尼·阿格威克2014年

1
我已经从git仓库创建了一个副本(只是为了在不破坏原始仓库的情况下“玩转”),并使其与源保持最新,Brian的答案正是我所需要的,所以,Cupcake,我不得不说,这不是“错误”,而是另一个用例。但您最好指出潜在的灾难:D
ferrari2k 2015年

6
IMO这需要成为公认的解决方案。另外,如果您想从中选择完遥控器后要删除它,请使用git remote rm projectB。也可git tag -d tag-name用于删除从远程仓库获取的所有标签。远程提交将不再显示在您的历史记录中,并且修剪将最终从存储中删除它们。
ADTC

130

您可以做到,但是需要两个步骤。就是这样:

git fetch <remote-git-url> <branch> && git cherry-pick FETCH_HEAD

替换<remote-git-url>为您要从中选择的存储库的URL或路径。

替换<branch>为要从远程存储库中挑选的分支或标记名称。

您可以FETCH_HEAD从分支中替换为git SHA。

更新:根据@pkalinow的反馈进行了修改。


8
它适用于分支名称,但不适用于SHA。如果您想挑选其哈希表示的提交,请改用:git fetch <repo-url> <branch> && git cherry-pick <sha>
pkalinow

谢谢。这正是我需要将多个提交从一个存储库插入到另一个存储库的目的,为此我创建了这些提交。
wojciii

这正是我针对不同客户(每个人都有自己的存储库/分支)的代码的许多自定义实现所需要的,我们需要一种将特定提交提交到我们的基础/主体中的方法。谢谢!
RedSands

对于回购中的一次性樱桃选择,这应该是公认的答案。在已经是本地的存储库之间进行选择时,我一直使用它,因此远程URL只是本地文件系统路径。
Amedee Van Gasse

61

以下是添加远程,获取分支和挑选提交的步骤

# Cloning our fork
$ git clone git@github.com:ifad/rest-client.git

# Adding (as "endel") the repo from we want to cherry-pick
$ git remote add endel git://github.com/endel/rest-client.git

# Fetch their branches
$ git fetch endel

# List their commits
$ git log endel/master

# Cherry-pick the commit we need
$ git cherry-pick 97fedac

资料来源:https : //coderwall.com/p/sgpksw


17

请参阅如何使用Git创建和应用补丁。(从您的问题的措辞中,我假设该其他存储库用于完全不同的代码库。如果它是同一代码库的存储库,则应按照@CharlesB的建议将其添加为远程存储。即使它用于另一个代码库,我想您仍然可以将其添加为远程数据库,但是您可能不想将整个分支添加到存储库中...)


11

您可以按以下方式一行完成。希望您在git存储库中,需要进行精心挑选的更改,并且您已经签出了正确的分支。

git fetch ssh://git@stash.mycompany.com:7999/repo_to_get_it_from.git branchToPickFrom && git cherry-pick 02a197e9533
# 

git fetch [分支URL] [从[ ] 分支到Cherry-pick] && git cherry-pick [提交ID]


1
干杯,不需要ssh://部分,只为https://
Leo


1

假设A您要从中选择仓库,并且B是您要选择的仓库,则可以通过添加</path/to/repo/A/>/.git/objects来实现</path/to/repo/B>/.git/objects/info/alternatesalternates如果此文件不存在,则创建它。

这将使存储库B访问存储库A中的所有git对象,并使您的樱桃选择工作。


0

我的情况是,我有一个空缺的存储库,该团队将其推送到该存储库中,并且旁边有一个克隆存储库。Makefile中的这组线对我来说正常工作:

git reset --hard
git remote update --prune
git pull --rebase --all
git cherry-pick -n remotes/origin/$(BRANCH)

通过使裸仓库的母版保持最新状态,我们可以挑选发布到裸仓库的建议更改。我们也有一种(更复杂的方法)选择多个分支进行合并的审查和测试。

如果“一无所知”的意思是“不能用作遥控器”,那么这没有帮助,但是由于我一直在搜寻该工作流程,所以出现了这样的SO问题,所以我想我会有所贡献。


-n根据git docs表示没有提交,我非常重要的一点是,在提交之前请先查看更改
canbax

0

如果要在给定提交之前选择多个给定文件的提交,请使用以下命令。

# Directory from which to cherry-pick
GIT_DIR=...
# Pick changes only for this file
FILE_PATH=...
# Apply changes from this commit
FIST_COMMIT=master
# Apply changes until you reach this commit
LAST_COMMIT=...

for sha in $(git --git-dir=$GIT_DIR log --reverse --topo-order --format=%H $LAST_COMMIT_SHA..master -- $FILE_PATH ) ; do 
  git --git-dir=$GIT_DIR  format-patch -k -1 --stdout $sha -- $FILE_PATH | 
    git am -3 -k
done
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.