ファイル変更時の自動バージョン管理(変更/作成/削除)


16

ディレクトリ内の変更を(再帰的に)自動的かつ透過的にバージョン管理するメカニズムの実装(Linux上)を探しています。これは、標準のバージョン管理(SVN、git、...)への追加(要求されたすべての機能が利用可能な場合は置き換えられる可能性がある)を目的としています。

これを行うMS Windows上の製品はAutoVerです(要件をよりよく理解するため)。そのようなものが欲しいのですが、非グラフィカル環境でのLinuxを目指しました。

Linuxでこの機能を使用する試みがいくつかあることがわかりました。私が見つけた最も近いものはSubversionでの自動バージョン管理ですが、既存の環境(たとえば、構成ファイルがローカルにあるサーバー)に実装するのは明らかではありません。

多分何かで動作しinotifyますか?

事前にありがとうございます!WoJ




使用するソフトウェアについて特別な要件はありますか?(ファイルを編集して)手動で行う変更の追跡のみを目的としている場合、Eclipseにはこの機能が組み込まれているため、「ローカル履歴」と呼ばれます。
ステファンザイデル

@StefanSeidel私は話題のスターターではありませんが、IDEなしのソリューションを好むでしょう。
マイケルパンコフ

回答:


5

1. bazaarとinotifyを使用した汎用メソッド

これはテストされていませんが、(bazaar)&を使用してディレクトリを監視し、bazaarを使用してその中のファイルをバージョン管理するこの記事を見つけました。bzrinotifywait

このスクリプトは、ディレクトリの変更を監視するすべての作業を実行します。

#!/bin/bash

# go to checkout repository folder you want to watch
cd path/to/www/parent/www
# start watching the directory for changes recusively, ignoring .bzr dir
# comment is made out of dir/filename
# no output is shown from this, but wrinting a filename instead of /dev/null 
# would allow logging
inotifywait –exclude \.bzr -r -q -m -e CLOSE_WRITE \
    –format=”bzr commit -m ‘autocommit for %w/%f’” ./ | \
    sh  2>/dev/null 1>&2 &
# disown the pid, so the inotify thread will get free from parent process
# and will not be terminated with it
PID=`ps aux | grep inotify | grep CLOSE_WRITE | grep -v grep | awk ‘{print $2}’`
disown $PID

# this is for new files, not modifications, optional
inotifywait –exclude \.bzr -r -q -m -e CREATE \
    –format=”bzr add *; bzr commit -m ‘new file added %w/%f’” ./ | \
    sh  2>/dev/null 1>&2 &
PID=`ps aux | grep inotify | grep CREATE | grep -v grep | awk ‘{print $2}’`
disown $PID

exit 0;

2. / etcの管理

システムの/etcディレクトリを管理する特別な場合には、アプリetckeeperを使用できます。

etckeeperは、/ etcをgit、mercurial、darcs、またはbzrリポジトリに保存するためのツールのコレクションです。apt(およびyumやpacman-g2を含む他のパッケージマネージャー)にフックして、パッケージのアップグレード中に/ etcに加えられた変更を自動的にコミットします。revison制御システムが通常サポートしないファイルメタデータを追跡しますが、/ etc / shadowの許可など、/ etcにとって重要です。それは非常にモジュール式で設定可能ですが、リビジョン管理の基本を理解していれば簡単に使用できます。

ここから始めるための良いチュートリアルがあります。

3. gitとincronを使用する

この手法はとを使用gitincronます。この方法では、次のことを行う必要があります。

A.リポジトリを作成する

% mkdir $HOME/git
% cd $HOME/git
% git init

B.$HOME/bin/git-autocommitスクリプトを作成する

#!/bin/bash

REP_DIR="$HOME/git"       # repository directory
NOTIFY_DIR="$HOME/srv"    # directory to version

cd $REP_DIR
GIT_WORK_TREE=$NOTIFY_DIR /usr/bin/git add .
GIT_WORK_TREE=$NOTIFY_DIR /usr/bin/git commit -a -m "auto"

C.エントリをincrontabに追加します

% sudo incrontab -e $HOME/srv IN_MODIFY,IN_CREATE,IN_MOVED_FROM,IN_MOVED_TO $HOME/bin/git-autocommit

4. Flashbakeを使用する

別のオプションは、Flashbakeのようなツールを使用することです。Flashbakeは、(BoingBoingで有名な)Cory Doctorowが本を書くために使用するバージョン管理システムです。

Flashbakeは、フードの下でgitを使用して変更を追跡しますが、自動バックアップを実行することと、単純なバージョン管理システムを使用することの間のどこかにあります。

Coryは、このバージョンにプロンプ​​ト、自動コミットが発生した時点のスナップショット、および彼が考えていたものを保持することを望んでいました。Pythonスクリプトをすばやくスケッチして、必要なコンテキスト情報を取得し、cronスクリプトがシェルラッパーを呼び出したときのコミットコメント用のPythonスクリプトの出力を使用して、シェルスクリプトをハッキングしてgitを起動し始めました。

資源


3
inotifywait + "git local" = gitwatch.sh、こちらをご覧ください:github.com/nevik/gitwatch/blob/master/gitwatch.sh
diyism

4

すぐにZFSが思い浮かびます。スナップショットを作成できます。また、スナップショット自動的に作成するプロジェクトがいくつかあります


私は、ZFSについて読んだが、それは(少なくとも、Linuxの場合)基本的なファイルシステムの安定したソリューションではありませんように見えます
WoJ

既存のFSにスナップするソリューションが本当に欲しいです。
マイケルパンコフ

おそらくこれ?ext3cow.com
ザックB

3

私はあなたが正しい軌道に乗っていると思いますinotifyこの記事では、あなたと同様のケースでの基本的な使用法について詳しく説明します。直接使用するか、fschangeのようなカーネルレベルのユーティリティをコンパイルすることをお勧めします。これは面倒ですが、変更の検出をにバインドすることもできますgit commit

これらのソリューションには、どちらかと言えば不完全なサードパーティのソリューションに依存するという問題があります。手を汚したくない場合は、NodeJSがこの正確な目的のための優れたクロスプラットフォーム機能(fs.watch)を提供します。NodeJSの変更についてファイルを監視する基本的なチュートリアルは、ここにあります。数十行以内で、ファイルのディレクトリを監視し、(child_processを介して)シェルアウトし、git commitまたは同様のものを実行する(または、手動でバージョンファイルインデックスをインクリメントする)ことができます。独自のアプローチ)。

fs.watchinotifyLinuxでサポートされていますが、より直感的に使用できます。他のNodeJSのプロジェクトがあり、そのラップそのファイルウォッチングのような利便性の様々なレベルでの機能をこの1、この1


まだ準備ができていない解決策であり、まあ、私はおそらくPythonを使いinotifyます。しかし、ありがとう。
マイケルパンコフ

3

Linuxのinotify(2)は大きなツリーを見ることができませんが、fuseファイルシステム(別の場所にマウントされている)はおそらくファイルシステム要求をsvnまたはgit呼び出しに変換するか、svn / gitメタデータを直接変更することで処理できます。

これは非常に興味深いアイデアですが、既存の実装について聞いたことはありませんでした。


ファイルが数個しかない場合を考えてみましょう。
マイケルパンコフ

0

このようなスクリプトを書くのは難しくありません。

私のお気に入りのバージョン管理はgitです。

次のスクリプトで実行する必要があります。

#!/bin/sh
git add .
git commit -am "my automatic commit"

定期的にディレクトリをチェックするか、保存後にエディターがスクリプト可能な呼び出しであるかを確認します。

しかし、このようにすると、大きなファイルや自動保存のような「役に立たない」ファイルを除外するのが理にかなっているかもしれません。


はい、cronベースのソリューションは簡単に実装できることを知っています。ただし、保存メカニズムに関係なく、保存時にバージョン管理されるものを探しています。これは、私の質問でinotifyと同様にsvnでautoversionninfに言及した理由でもあります。
WoJ

0

SparkleShare(http://sparkleshare.org)はgitに基づいており、バージョン管理を備えたDropbox-Like機能を実装していますが、ssh-server(localhostの場合もあります)を設定する必要があります。


このことは不器用で、多くのセットアップが必要です。また、Dropboxの機能は不要です。
マイケルパンコフ


0

rsyncとcronジョブのみを使用してこれを行う「貧乏人」の方法もあります。基本的にrsyncのバックアップ機能に依存し、2つの個別のパスとプレフィックス/サフィックスを使用してファイルを追跡します。

以下のように見えます:/ usr / bin / rsync -a -A -X --backup --suffix = date +".%Y-%m-%d_%H-%M-%S"$ source_path $ backup_path

最終結果:最初の実行後にソースパスのtest_rsyncというファイルを変更すると、test_rsync.2017-02-09_11-00-01というファイルがバックアップパスに作成されます。

これには多くの問題があります(ファイルの数がまともな場合にのみ機能し、rsyncの2つの連続した実行(私の場合は1分)の間に発生する変更に対して失敗します)が、それはあなたのニーズに十分かもしれません。

ここでsamba共有について話している場合、除外リストが適切である可能性があります。

これを改善したら教えてください。


0

これは、保存時に元のファイル名にタイムスタンプを追加して自動ファイルバージョン管理のようなVMSを実行するPython3スクリプトです。

スクリプトにたくさんのコメントを入れ、ubuntuマシンでこのようなスクリプトを半ダース実行しました。スクリプトのバージョンごとに異なるディレクトリのみを使用して、複数のディレクトリを同時にバージョン管理しています。マシンのパフォーマンスに実質的なペナルティはありません。

!/ usr / bin / env python3

print( "PROJECT FILES VERSIONING STARTED")print( "version_creation.py")#このすべてのコードをこの名前のスクリプトに配置print( "run as .. 'python3 version_creation.py' from command line")print( "ctrl ' c 'to stop ")print(" ")print("コマンドラインで以下のバックグラウンドでプログラムを実行し、ウィンドウを閉じます。 ")print(" nohup python3 version_creation.py ")print(" .... to停止プロセスgo menu / administration / system monitor ... and kill python3 ")print(" ")print("常に「ProjectFiles」ディレクトリにファイルを保存し、バージョンファイル ")print("もそのディレクトリに作成されます。 。 ")print(" ")print(" ")print(" ")print(" ")

import shutil import osインポート時間

---新しいファイルをチェックする時間間隔を設定します(秒単位)

-この間隔は、新しいファイルが表示される間隔よりも小さくする必要があります!

t = 10

---ソースディレクトリ(dr1)とターゲットディレクトリ(dr2)を設定します

dr1 = "/ path / to / source_directory"

dr2 = "/ path / to / target_directory"

import glob import os

dr1 = "/ home / michael / ProjectFiles"#オリジナルとバージョンの両方がこのディレクトリに保存されます

dr2 = "/ home / michael / ProjectFileVersions"

Trueの場合:

if os.listdir(dr1) == []:

印刷(「空」)

    n = 100
else:
    list_of_files = glob.glob(dr1+'/*')   # * means all if need specific format then *.csv
    latest_file_path = max(list_of_files, key=os.path.getctime)

print( "1 Latest_file_path ="、latest_file_path)

    originalname = latest_file_path.split('/')[-1]

print( "2 originalname ="、originalname)

    filecreation = (os.path.getmtime(latest_file_path))

print( "filecreation ="、filecreation)

    now = time.time()
    fivesec_ago = now - 5 # Number of seconds

print( "fivesec_ago ="、fivesec_ago)

    timedif = fivesec_ago - filecreation #time between file creation

print( "timedif ="、timedif)

    if timedif <= 5: #if file created less than 5 seconds ago

        nameroot = originalname.split(".")[-0]
        print ("3 nameroot= ", nameroot)

        extension = os.path.splitext(originalname)[1][1:]
        print ("4 extension = ", extension)

        curdatetime = time.strftime('%Y%m%d-%H%M%S')
        print ("5 curdatetime = ", curdatetime)

        newassembledname = (nameroot + "_" + curdatetime + "." + extension)
        print ("6 newassembledname = ", newassembledname)



        source = dr1+"/"+originalname
        print ("7 source = ", source)

        target = dr1+"/"+newassembledname
        print ("8 target = ", target)

        shutil.copy(source, target)


    time.sleep(t)

共有

以下は以前に入れられて動作しますが、私は上記のPythonスクリプトがはるかに好きです......(約3時間Pythonを使用しています)

#!/usr/bin/env python3

print ("PROJECT FILES VERSIONING STARTED")
print ("projectfileversioning.py")
print ("run as..  'python3 projectfileversioning.py'       from command line")
print ("ctrl 'c'      to stop")
print (" ")
print ("To run program in background type below to command line and then close the window. ")
print ("nohup python3 projectfileversioning.py")
print ("....to stop process go menu/administration/system monitor... and kill python")
print (" ")
print ("Always save files to the 'ProjectFiles' directory and the file ")
print ("   will be redirected to the ProjectFileVersions where")
print ("   time stamped versions will also be created.")
print (" ")
print ("If you like you may then copy/move the versioned and original file from 'ProjectFileVersions' to ")
print ("any other directory you like.")

import shutil
import os
import time

#--- set the time interval to check for new files (in seconds) below 
#-   this interval should be smaller than the interval new files appear!
t = 10

#--- set the source directory (dr1) and target directory (dr2)
#dr1 = "/path/to/source_directory"
#dr2 = "/path/to/target_directory"

import glob
import os

dr1 = "/home/michael/ProjectFiles"
dr2 = "/home/michael/ProjectFileVersions"


while True:

    if os.listdir(dr1) == []:
        n = 100
    else:
        list_of_files = glob.glob(dr1+'/*')   # * means all if need specific format then *.csv
        latest_file_path = max(list_of_files, key=os.path.getctime)
        print ("1 Latest_file_path = ", latest_file_path)

        originalname = latest_file_path.split('/')[-1]
        print ("2 originalname = ", originalname)

        nameroot = originalname.split(".")[-0]
        print ("3 nameroot= ", nameroot)

        extension = os.path.splitext(originalname)[1][1:]
        print ("4 extension = ", extension)

        curdatetime = time.strftime('%Y%m%d-%H%M%S')
        print ("5 curdatetime = ", curdatetime)

        newassembledname = (nameroot + "_" + curdatetime + "." + extension)
        print ("6 newassembledname = ", newassembledname)




        source = dr1+"/"+originalname
        print ("7 source = ", source)

        target = dr2+"/"+originalname
        print ("8 target = ", target)

        shutil.copy(source, target)



        source = dr1+"/"+originalname
        print ("9 source = ", source)

        target = dr2+"/"+newassembledname
        print ("10 target = ", target)

        shutil.move(source, target)
        time.sleep(t)


#share
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.