# local code here
merge
引言
当使用 jupyter notebook(它们在后台是 json 文件)和 GitHub 时,合并冲突(会在 notebook 源文件中添加新行)非常普遍,这会导致你正在处理的一些 notebook 损坏。此模块定义了函数 nbdev_fix
来为你修复这些 notebook,并尝试自动合并标准冲突。剩余的冲突将由 markdown 单元格界定,如下所示
<<<<<< HEAD
======
# remote code here
>>>>>> a7ec1b0bfb8e23b05fd0a2e6cafcb41cd0fb1c35
下面是一个损坏的 notebook 示例。json 格式被 git 自动添加的行破坏了。这样的文件无法在 jupyter notebook 中打开。
= Path('../../tests/example.ipynb.broken')
broken = broken.read_text(encoding='utf-8')
tst_nb print(tst_nb)
{
"cells": [
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
<<<<<<< HEAD
"z=3\n",
=======
"z=2\n",
>>>>>>> a7ec1b0bfb8e23b05fd0a2e6cafcb41cd0fb1c35
"z"
]
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6"
]
},
<<<<<<< HEAD
"execution_count": 7,
=======
"execution_count": 5,
>>>>>>> a7ec1b0bfb8e23b05fd0a2e6cafcb41cd0fb1c35
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x=3\n",
"y=3\n",
"x+y"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
请注意,在这个例子中,第二个冲突很容易解决:它只涉及第二个单元格的执行计数,并且通过选择任一选项而不会真正影响你的 notebook 就可以解决。这类冲突我们将自动修复。第一个冲突则更复杂,因为它跨越了两个单元格,并且其中一个版本存在一个单元格,而另一个版本没有。这样的冲突(通常是单元格输入内容从一个版本变为另一个版本的冲突)不会自动修复,但我们会返回一个合适的 json 文件,其中 git 引入的注释将被放在 markdown 单元格中。
创建合并的 notebook
我们使用的方法是首先“unpatch”冲突的文件,重新生成它最初创建的两个文件。然后我们重新进行 diff 过程,但使用单元格而不是文本行。
unpatch
unpatch (s:str)
接受带有冲突标记的字符串,并返回两个原始文件及其分支名称
对我们冲突的测试 notebook 进行“unpatch”的结果是它本应创建的两个原始 notebook。每个原始 notebook 都将包含有效的 JSON。
= unpatch(tst_nb)
a,b,branch1,branch2 dict2nb(loads(a))
{ 'cells': [ { 'cell_type': 'code',
'execution_count': 6,
'idx_': 0,
'metadata': {},
'outputs': [ { 'data': {'text/plain': ['3']},
'execution_count': 6,
'metadata': {},
'output_type': 'execute_result'}],
'source': 'z=3\nz'},
{ 'cell_type': 'code',
'execution_count': 5,
'idx_': 1,
'metadata': {},
'outputs': [ { 'data': {'text/plain': ['6']},
'execution_count': 7,
'metadata': {},
'output_type': 'execute_result'}],
'source': 'x=3\ny=3\nx+y'},
{ 'cell_type': 'code',
'execution_count': None,
'idx_': 2,
'metadata': {},
'outputs': [],
'source': ''}],
'metadata': { 'kernelspec': { 'display_name': 'Python 3',
'language': 'python',
'name': 'python3'}},
'nbformat': 4,
'nbformat_minor': 2}
dict2nb(loads(b))
{ 'cells': [ { 'cell_type': 'code',
'execution_count': 6,
'idx_': 0,
'metadata': {},
'outputs': [ { 'data': {'text/plain': ['3']},
'execution_count': 6,
'metadata': {},
'output_type': 'execute_result'}],
'source': 'z=2\nz'},
{ 'cell_type': 'code',
'execution_count': 5,
'idx_': 1,
'metadata': {},
'outputs': [ { 'data': {'text/plain': ['6']},
'execution_count': 5,
'metadata': {},
'output_type': 'execute_result'}],
'source': 'x=3\ny=3\nx+y'},
{ 'cell_type': 'code',
'execution_count': None,
'idx_': 2,
'metadata': {},
'outputs': [],
'source': ''}],
'metadata': { 'kernelspec': { 'display_name': 'Python 3',
'language': 'python',
'name': 'python3'}},
'nbformat': 4,
'nbformat_minor': 2}
branch1,branch2
('HEAD', 'a7ec1b0bfb8e23b05fd0a2e6cafcb41cd0fb1c35')
nbdev_fix
nbdev_fix (nbname:str, outname:str=None, nobackup:<function bool_arg>=True, theirs:bool=False, noprint:bool=False)
从冲突的 notebook nbname
创建工作 notebook
类型 | 默认值 | 详情 | |
---|---|---|---|
nbname | str | 要修复的 Notebook 文件名 | |
outname | str | None | 输出 notebook 的文件名(默认为 nbname ) |
nobackup | bool_arg | True | 如果未提供 outname ,则不将 nbname 备份到 nbname .bak |
theirs | bool | False | 使用他们的输出和元数据而非我们的 |
noprint | bool | False | 不打印有关是否找到冲突的信息 |
首先可选地将 notebook fname
备份到 fname.bak
,以防万一出错。然后它解析损坏的 json,解决单元格中的冲突。每个仅涉及单元格元数据或输出的冲突将通过使用本地分支 (theirs==False
) 或远程分支 (theirs==True
) 自动解决。否则,或对于涉及单元格输入内容的冲突,json 将通过包含冲突单元格的两个版本以及指示冲突的 markdown 单元格来修复。你将能够再次打开 notebook 并搜索冲突(查找 <<<<<<<
),然后根据需要修复它们。
将打印一条消息,指示 notebook 是完全合并还是仍有冲突。
='tmp.ipynb')
nbdev_fix(broken, outname= read_nb('tmp.ipynb')
chk len(chk.cells), 7)
test_eq('tmp.ipynb') os.unlink(
One or more conflict remains in the notebook, please inspect manually.
Git 合并驱动
nbdev_merge
nbdev_merge (base:str, ours:str, theirs:str, path:str)
notebook 的 Git 合并驱动
这为 notebook 实现了一个 git 合并驱动,它可以自动解决冲突的元数据和输出,并将剩余的冲突拆分为单独的单元格,以便在 Jupyter 中查看和修复 notebook。安装它的最简单方法是运行 nbdev_install_hooks
。
这通过首先运行 Git 的默认合并驱动,然后在仍有冲突时运行 nbdev_fix
来工作。你可以使用 THEIRS
环境变量设置 nbdev_fix
的 theirs
参数,例如
THEIRS=True git merge branch