我想做“最艰难的版本”的Cherry-Pick / Merge / Rebase / Checkout,这意味着我分支上的应用程序状态开始看起来完全像在Cherry-Picked提交中(但保留历史记录)我的分支机构)。实际上,我可以复制我的仓库,删除分支中的所有内容,然后从复制版本集中复制全部内容到所需提交。但是,这并不方便,我相信有一些更简单的方法。
我已经尝试过git cherry-pick <hash> --strategy-option theirs
,但这并不完美,因为它不会删除在经过精心挑选的提交中不存在的文件,这对我来说是一个大麻烦。
那我该怎么办?
编辑:我澄清了我还需要保留我的历史记录,这首先是不明显的。
答案 0 :(得分:3)
那根本不是挑樱桃。不要用git cherry-pick
来做:要用git commit
来做。这是一个非常简单的配方 1 :
$ git checkout <branch> # get on the target branch
$ cd $(git rev-parse --show-toplevel) # ensure you're at the top of the work-tree
$ git rm -r . # remove all tracked files from index and work-tree
$ git checkout <hash> -- . # create every file anew from <hash>
$ git commit # make a new commit with all new info
如果您要从提交<hash>
复制提交消息等,请考虑在-c <hash>
行中添加git commit
。
1 这不是最简单的,但应该可以理解。较简单的命令在初始git checkout
之后使用管道命令,例如:
git read-tree -u <hash>
git commit
或:
git merge --ff-only $(git commit-tree -p HEAD <hash>^{tree} < /tmp/commit-msg)
(未经测试,第二个则必须构造一个提交消息)。
请记住,Git存储了提交,每个提交都是所有源文件以及一些元数据的完整快照。每次提交的元数据都包括提交者的姓名和电子邮件地址;提交时间的日期和时间戳记;一条日志消息,说明为什么为什么;对于Git来说,至关重要的是提交的 parent 的哈希ID。
只要您具有某个提交的哈希ID,我们就说您指向提交。如果一个提交具有另一个提交的哈希ID,则带有哈希ID的提交将指向另一个提交。
这意味着嵌入在每个提交中的这些哈希ID构成了一个向后看的链。如果我们使用单个字母代表提交,或按顺序对它们进行编号C1
,C2
,依此类推,则得到:
A <-B <-C <-D ... <-G <-H
或:
C1 <-C2 <-C3 ... <-C7 <-C8
每次提交的实际名称当然是一些丑陋的哈希ID,但是使用这样的字母或数字会使我们(人类)更容易处理它们。无论如何,关键是如果我们以某种方式将 last 提交的哈希ID保存在链中,那么我们最终就可以向后跟踪链的其余部分,一次提交一次
我们在Git中存储这些哈希ID的位置位于分支名称中。因此,像master
这样的分支名称只存储提交H
的真实哈希ID,而H
本身存储其父G
的哈希ID,后者存储的是{其父F
,依此类推:
... <-F <-G <-H <-- master
这些从H
到G
到F
的后向链接,以及每次提交保存的快照,以及有关谁进行提交以及为什么进行提交的元数据, 您存储库中的历史记录。要保留以H
结尾的历史记录,您只需要确保在进行 next 提交时,将H
作为其父级:
...--F--G--H--I <-- master
通过进行新的提交,Git更改名称master
来记住新的提交I
的哈希ID,其父是H
,其父是(仍然){{1 }},等等。
您的目标是使用与其他提交(例如下面的G
)相关的快照进行提交I
:
K
Git实际上是根据 index 中的内容而不是源代码树中的内容构建新的提交的。因此,我们从...--F--G--H <-- master
\
J------K------L <-- somebranch
开始,将提交git checkout master
设为当前提交,并将H
设为当前分支,这将从提交master
的内容中填充索引和工作树。
接下来,我们希望索引匹配提交H
(除了K
中没有其他文件之外),因此我们首先从索引中删除每个文件。为了保持理智(即让我们可以看到我们在做什么),我们让Get对工作树执行相同的操作,该工作树会自动执行。因此,在确保K
指向整个索引/工作树对之后,我们运行git rm -r .
,方法是确保我们位于工作树的顶部而不是某个子目录/子文件夹。
现在,只有未跟踪的文件保留在我们的工作树中。如果愿意,我们也可以使用普通的.
或rm
删除它们,尽管在大多数情况下它们是无害的。如果您希望删除它们,请随时执行此操作。然后,我们需要从提交git clean
来填充索引(工作树再一次出现),因此我们运行K
。 git checkout <hash-of-K> -- .
很重要:它告诉Git 不要 switch 提交,只需从此处命名的提交中提取所有内容即可。现在,我们的索引和工作树与commit匹配-- .
。
(如果提交K
具有我们在K
中拥有的 all 个文件,则可以跳过H
步骤。我们只需要{{1} } 删除 git rm
中但不在git rm
中的文件。)
最后,现在我们有了与提交H
匹配的索引(和工作树),我们可以安全地进行类似于K
的新提交,但不会将连接到 K
。
K
以上序列导致:
K
其中提交{{1}中的保存的源快照与提交git merge --no-commit
中的完全匹配。但是,历史记录是通过读取...--F--G--H--I <-- master
\
J-------K-----L <-- somebranch
,发现其指向I
,然后读取提交K
以及向后指向master
,I
和{ {1}},依此类推,绝对不要提及提交I
。
您可能想要的是这样的历史记录:
H
在这里,提交G
会回到两者提交F
和 K
。
使提交...--F--G--H--I <-- master
\ /
J-------K-----L <-- somebranch
成为这种变体有点棘手,因为除了使用I
管道命令之外,唯一使 make 提交H
的方法是使用K
。
在这里,简单的方法是运行I
,如下所示:
git commit-tree
我们在这里使用I
使事情变得更快,更流畅。我们正在构建的实际上是git merge
的结果,除了没有git merge -s ours --no-commit
的事实。 $ git merge -s ours --no-commit <hash> # start the merge but don't finish it
$ git rm -r . # discard everything
$ git checkout <hash> -- . # replace with their content
$ git commit # and now finish the merge
的意思是忽略他们的提交,只保留我们提交的内容-s ours
。然后我们将其丢弃,并用他们提交git merge -s theirs
的内容替换,然后完成合并以获得指向git merge -s theirs
和-s ours
的合并提交H
。
和以前一样,有 个管道命令技巧使此操作更加容易。除非您了解Git内部使用的低级存储格式,否则它们并不是显而易见的。 “删除所有内容,然后检出不同提交内容的方法”确实很明显,而且很容易记住。
答案 1 :(得分:2)
您需要使用Q1 = Label(fenetre2, text="1) Comment se nomme le président français?", font='Helvetica 10 bold')
Q1.pack()
Q1A = Radiobutton(fenetre2, text="Nicolas Sarkozy", value=2, variable=rep1)
Q1A.pack()
Q1B = Radiobutton(fenetre2, text="Emmanuel Macron", command=ajouter1, value=1, variable=rep1)
Q1B.pack()
Q1C = Radiobutton(fenetre2, text="François Hollande", value= 3, variable=rep1)
Q1C.pack()
def ajouter1():
global score
score+=1
Score = "Bravo, Votre score est de: " + str(score) + "/10"
var_label.set(Score)
Score = Label(fenetre3, textvariable=var_label, font='Helvetica 10 bold')
var_label.set("Bravo, Votre score est de: 0/10")
Score.pack()
。首先,合并...策略或结果无关紧要。如果有冲突,没关系...添加所有文件并保存(不用担心...我们将在一秒钟内修改正确的内容)。
现在,签出您要从中获取内容的修订。如果是分支,请使用git reset --soft
。现在,--detach
到原始分支(我们之前进行过合并的位置)。
现在完成技巧的运行git reset --soft
,您就完成了。如果您喜欢结果,请使用git commit --amend --no-edit
移动原始分支的分支指针,然后完成。
原始收据,但不保存其他分支的历史记录
您要做的是git branch -f the-original-branch
。检出您希望另一个分支看起来像(内容方面)的修订版(或带有--detach的分支)。然后执行git reset --soft
。这样会将分支 pointer 设置为此版本或分支,工作树将类似于我们之前检出的树,并且它们之间的所有差异都将在索引上。现在,当您提交时,您将获得一个修订版本,该分支的外观将与您首先签出的原始版本相似。...如果您喜欢最终结果,请移动分支指针并将其签出。
答案 2 :(得分:0)
$ git checkout --orphan new-branch-name
$ git cherry-pick <hash>