Задать вопрос
@ImagineTables

Как сделать автокоммит текстового файла в git при сохранении в Notepad++?

Есть постоянно редактируемый в Notepad++ текстовый файл. Хотелось бы при каждом изменении коммитить его автоматически. Чтобы 1) потом смотреть дату каждого изменения, 2) ничего не потерять при удалении.

Попробовал поставить плагин NppExec, но его скрипты нельзя повесить на сохранение.

Железяка предложила написать скрипт на PowerShell, который отслеживал бы изменения файла на диске, но это за ним следить придётся. Свой сервис программировать не хочется. Нет ли у вас идей?
  • Вопрос задан
  • 265 просмотров
Подписаться 2 Простой 5 комментариев
Помогут разобраться в теме Все курсы
  • Нетология
    1C-программист: расширенный курс
    18 месяцев
    Далее
  • Академия Эдюсон
    Python-разработчик + ИИ
    9 месяцев
    Далее
  • ProductStar × РБК
    Профессия: Python-разработчик + ИИ
    8 месяцев
    Далее
Решения вопроса 2
sergey-kuznetsov
@sergey-kuznetsov Куратор тега Git
Автоматизатор
Можно сделать прямо внутри Notepad++ через плагин PythonScript.

У PythonScript есть событие NOTIFICATION.FILESAVED, на которое можно повесить git add и git commit. Отдельный watcher или NppExec для этого не нужен.

Проверил у себя — работает.

Установка и настройка

  1. Открыть Plugins → Plugins Admin....
  2. Найти PythonScript, отметить его и нажать Install. Notepad++ после установки перезапустится.
  3. Открыть Plugins → PythonScript → Configuration....
  4. Для Initialisation выбрать ATSTARTUP. Заодно полезно включить Automatically open console on error, чтобы ошибки скрипта сразу были видны.
  5. Открыть Plugins → PythonScript → Scripts и startup (User). Если пользовательского startup.py ещё нет — создать через Plugins → PythonScript → New Script файл с именем startup.py.
  6. Вставить в него следующий код и сохранить:


from Npp import notepad, NOTIFICATION
import os
import subprocess
import datetime


def on_save(args):
    filename = notepad.getBufferFilename(args["bufferID"])
    file_dir = os.path.dirname(filename)

    try:
        repo = subprocess.check_output([
            "git", "-C", file_dir,
            "rev-parse", "--show-toplevel"
        ]).strip()
    except subprocess.CalledProcessError:
        return

    rel_file = os.path.relpath(filename, repo)

    subprocess.call([
        "git", "-C", repo,
        "add", "--", rel_file
    ])

    changed = subprocess.call([
        "git", "-C", repo,
        "diff", "--cached", "--quiet",
        "--", rel_file
    ])

    if changed != 0:
        message = "autosave " + datetime.datetime.now().strftime(
            "%Y-%m-%d %H:%M:%S"
        )

        subprocess.call([
            "git", "-C", repo,
            "commit",
            "-m", message,
            "--", rel_file
        ])


notepad.callback(on_save, [NOTIFICATION.FILESAVED])


После перезапуска Notepad++ обработчик будет регистрироваться автоматически.

При каждом сохранении файла скрипт:

  1. получает путь сохранённого файла;
  2. через git rev-parse --show-toplevel определяет его Git-репозиторий;
  3. добавляет в индекс только этот файл;
  4. создаёт commit, только если содержимое действительно изменилось.


Если открытый файл находится не в Git-репозитории, ничего не происходит.

Разумеется, git должен быть установлен и доступен через PATH, а файл должен находиться внутри уже созданного Git-репозитория.

Есть только один нюанс: стабильная версия PythonScript, устанавливаемая через Plugins Admin, всё ещё использует встроенный Python 2.7. Поэтому скрипт написан без конструкций современных версий Python.

Если Git нужен только ради истории изменений одного текстового файла, то есть ещё более простой вариант — встроенный в Notepad++:

Settings → Preferences → Backup → Backup on save → Verbose backup


Он сохраняет отдельную предыдущую версию файла при каждом сохранении.

И ещё: локальный Git без push — это история версий, но не полноценный backup. При потере диска вместе с рабочей папкой пропадёт и каталог .git. Если нужна именно резервная копия, репозиторий надо периодически отправлять во внешнее хранилище.
Ответ написан
@ImagineTables Автор вопроса
Вот моя версия, основанная на ответе Сергей Кузнецов. Она асинхронная и не тормозит + окно консоли гита не мигает.

from Npp import notepad, NOTIFICATION
import os
import subprocess
import datetime
import threading

expected_folder = r"C:\path\to\folder"

def git_auto_commit(path):
    def task():
        work_dir = os.path.dirname(path)
        timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        msg = "Auto-commit on save: {0} at {1}".format(path, timestamp)
        # Flag to hide the console window
        CREATE_NO_WINDOW = 0x08000000

        # git add
        p1 = subprocess.Popen(
            ["git", "add", path],
            cwd=work_dir,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            creationflags=CREATE_NO_WINDOW
        )
        p1.communicate()

        # git commit
        p2 = subprocess.Popen(
            ["git", "commit", "-m", msg],
            cwd=work_dir,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            creationflags=CREATE_NO_WINDOW
        )
        p2.communicate()

    threading.Thread(target=task).start()

def is_subfolder_case_insensitive(path, folder):
    return path.lower().startswith(folder.lower())

def on_save(args):
    filename = notepad.getBufferFilename(args["bufferID"])

    if not is_subfolder_case_insensitive(filename, expected_folder):
        return

    git_auto_commit(filename)

notepad.callback(on_save, [NOTIFICATION.FILESAVED])
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
opium
@opium
Просто люблю качественно работать
Раз самому сервис писать неохота — не пиши его руками, заверни готовый PowerShell-скрипт с FileSystemWatcher через nssm:
nssm install AutoCommit powershell.exe -ExecutionPolicy Bypass -File "C:\scripts\watcher.ps1"
(путь к скрипту — обязательно полный, служба стартует не из твоей папки). Утилита сама регистрирует его как обычный Windows-сервис с автозапуском и рестартом при падении, никакого своего кода для демонизации писать не надо. Плюс работает для любого редактора, не только для Notepad++, в отличие от варианта через PythonScript.
Ответ написан
Комментировать
master_z
@master_z
Программист
Как я понял, вы хотите, чтобы по CTRL+S срабатывала автофиксация в .git хранилище.
Задача решаема, причём далеко не одним способом — вижу 4 варианта. Один приоритетный вам уже дали, так что не буду повторяться.
Из альтернатив: классика — TortoiseGit, через ПКМ делаете commit с комментарием. Или скрипт рядом с проектом — запустили, и всё. Но скрипт, на мой взгляд, менее удобен, чем Tortoise через ПКМ.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы