hi~, I don't know what happend with my notebook yeasterday, I find that some import code of my one notebook is missing this morning, and the checkpont is the same~
So why don't have multipe checkpoint at every saving time ?
So I modidy the code: notebook/services/contents/fileio.py

It woks~

that will be added to future version of notebook?
Thanks~
Si
The checkpoint is updated whenever you save manually; the only difference is that the checkpoint isn't updated by autosave.
We don't want to try to support multiple checkpoints by default, because that would be reinventing version control badly.
I agreed with your opinion before a few days ago, but sometimes I deleted some cells of codes and didn't realize that and save auto or manually, So missing the lost code forever. I just want to do some things in case of missing some cell of codes~
We recommend using version control - which usually means git these days. Github has some tutorials if you're not familiar with git: https://help.github.com/ . You can also setup nbdime to make a better experience with notebooks in version control.
ok, I will try nbdime later~
Thanks~
No problem :-)
I will really appreciate a feature like this since as far as I know the undo functionality is limited to undo deleted cells.
BTW, a VCS usually does not replace a undo tree.
We recommend using version control - which usually means git these days.
Yes, but I don't want a big fancy official save of changes. I'm not going to publish this. I want a checkpoint. This is safety net, not version control.
Inspired from @orangeSi extended his code for creating local git repos in every .ipynb_checkpoints directory.
It will create commit whenever someone saves a notebook and the author of commit will be the hostname of machine that is available along with the ip.
#jupyter_git_patch.py
# jupyter-git-patch start
def copy2_safe(src, dst, log=None):
"""copy src to dst
like shutil.copy2, but log errors in copystat instead of raising
"""
shutil.copyfile(src, dst)
try:
if dst.count('{0}.ipynb_checkpoints{0}'.format(os.sep)):
chkpoint = dst.split(__import__("os").sep)[-1]
ipydir = dst.rstrip(chkpoint)
r = 0
try:
r = __import__("git").Repo(ipydir)
except __import__("git").exc.InvalidGitRepositoryError:
r = __import__("git").Repo.init(ipydir)
if [1 for d in r.index.diff(None) if chkpoint in d.a_path] or chkpoint in r.untracked_files:
saviuser,saviuserr = "defaulter","defaulterr"
try:
frameno=4#py3
saviuser = __import__("inspect").getouterframes(__import__("inspect").currentframe())[frameno][0].f_locals['self'].request.remote_ip
saviuserr = __import__("socket").gethostbyaddr(saviuser)[0]
except Exception as e:
print("Attempt remote user detection: py3 failed:{} Trying py2 now.".format(e))
try:
frameno=10#py2
saviuser = __import__("inspect").getouterframes(__import__("inspect").currentframe())[frameno][0].f_locals['self'].request.remote_ip
saviuserr = __import__("socket").gethostbyaddr(saviuser)[0]
except Exception as e2:
print("Failed in remote user detection:", e2)
r.config_writer().set_value("user", "name", saviuserr).release()
r.config_writer().set_value("user", "email", saviuser).release()
try:
r.git.add(chkpoint)
except (__import__("git").exc.GitCommandError, IOError):
if sum(__import__("traceback").format_exc().count(_c) for _c in "Unable to create,index.lock,: File exists.".split(','))>2:
# index.lock needs to be deleted.
__import__("time").sleep(1)
to_delete=__import__("os").sep.join([ipydir, ".git", "index.lock"])
__import__("os").remove(to_delete)
print("Git commit: Deleted older existing git-locks.. Retrying to commit..[{}]".format(to_delete))
r.git.add(chkpoint)
r.index.commit(chkpoint.rstrip('checkpoint.ipynb') + __import__("datetime").datetime.now().isoformat())
except Exception as e:
print ("Git commiting failed as:", e,'\n',__import__("traceback").format_exc())
try:
shutil.copystat(src, dst)
except OSError:
if log:
log.debug("copystat on %s failed", dst, exc_info=True)
# jupyter-git-patch end
PS: Commit shall contain only the particular file and not the whole directory.
In Dockerfile (for those using jupyter out of docker):
#apply auto-git patch of jupyter
COPY jupyter_git_patch.py /tmp/jupyter_git_patch.py
RUN /opt/conda/bin/pip install gitpython
RUN cat /tmp/jupyter_git_patch.py >> /opt/conda/lib/python3.7/site-packages/notebook/services/contents/fileio.py
Although, this is not a recommended approach, I used in this in my project to track which user did what changes in a notebook.
To revert, one would have to go the .ipynb_checkpoints directory and git revert that particular commit.
The full code from OrangeSi:
def copy2_safe(src, dst, log=None):
"""copy src to dst
like shutil.copy2, but log errors in copystat instead of raising
"""
shutil.copyfile(src, dst)
try:
shutil.copystat(src, dst)
except OSError:
if log:
log.debug("copystat on %s failed", dst, exc_info=True)
if re.search(".ipynb_checkpoints",dst):
now= datetime.datetime.now()
now = re.sub(':','.',now.isoformat())
now = re.sub('-','.',now)
dst = dst+"."+now
shutil.copyfile(src,dst)
try:
shutil.copystat(src,dst)
except OSError:
if log:
log.debug("copystat on %s failed",dst,exc_info=True)
Most helpful comment
I will really appreciate a feature like this since as far as I know the undo functionality is limited to undo deleted cells.
BTW, a VCS usually does not replace a undo tree.