4

私と別の開発者は、他のコードからアクセスされる API を開発しています。ニーズに合わせて API の動作を変更する際には、API を使用する既存のアプリケーションをすぐに更新する必要がないように、古いバージョンを非推奨にすることなく API の追加バージョンをリリースします。例えば:

$ cat 0.5.php
<?php
$username = $_POST['name'];
?>

$ cat 0.6.php
<?php
$username = $_POST['username'];
?>

新しいバージョンを開始するときは、通常、cpN-1.php を N.php にバージョンアップし、そこからコーディングします。ただし、Git でこれを行うと、比較および元に戻すためにファイルからblamediff、およびその他の履歴全体が失われます。古いファイルのこの履歴を新しいファイルに「偽造」して、、、、などのコマンドが追加のフラグや引数を提示せずに「機能する」ようにするにはどうすればよいblameですか?logdiff--follow

4

6 に答える 6

10

-C旗を使いたい。これにより、コピーと名前の変更が検出されるため、履歴をたどることができます。 diffblame、およびlogこのフラグを受け入れます。

@madara-uchiha が言ったように、タグの使用を検討し、git-x.y代わりにタグからファイルを生成する必要があります。次のようなものを使用して、特定のタグでファイルの内容を取得できます。

git show v0.6:git.php > git-0.6.php

v0.6気になるタグはどこ?

更新

これを行うための小さなスクリプトを次に示します。この最初のものは、タグがx.yorの形式であることを前提としていますx.y.z:

#!/bin/bash
versions=$(git tag -l | egrep -o '^[0-9]+\.[0-9]+(\.[0-9]+)?$')
for version in $versions
do
    git show $version:git.php > git-$version.php
done

タグがvX.Yorの形式であり、ファイル名としてorvX.Y.Zが必要な場合、これは機能します。git-x.y.phpgit-x.y.z.php

#!/bin/bash
versions=$(git tag -l | egrep -o '^v[0-9]+\.[0-9]+(\.[0-9]+)?$')
for version in $versions
do
    git show $version:git.php > git-${version/#v/}.php
done

このスクリプトをリリース プロセスの一部として実行すると、すべてのバージョンが生成されます。git-また、名前からを削除するのは非常に簡単です。たとえば、 に> git-$version.phpなり> $version.phpます。

于 2013-06-27T12:49:40.803 に答える
6

バージョン管理が物事を処理する方法とAPIが公開される方法(つまり、Webサーバーが物事を処理する方法)を組み合わせようとしているように見えるという点で、あなたはこれを少し曇らせていると思います。

API の複数のバージョンが同時に機能するためには、コンシューマーはおそらく、特定の呼び出しに使用するバージョンを指定する必要があります。この回答では、バージョンが API URL の最初の「ディレクトリ」コンポーネントとして指定されるように、Stack Exchange API と同様の方法で作業していると仮定します (たとえば、バージョン 1.5 の場合、リクエストをhttp://domain.tld/1.5/call、私が使用するバージョン 1.6http://domain/1.6/?method=callなど)。しかし、適切なバージョンを決定し、Web サーバー レベルで要求を正しいコントローラーにルーティングするための何らかのメカニズムがある限り、実際にはこの要素は重要ではありません。

バージョン管理

ここでのアプローチは非常に単純です。すべてのバージョンは、リポジトリ内に独自のブランチを取得します。そのバージョンに対して実行される開発作業は、バージョンのブランチからのブランチで実行されるか、バージョンに直接コミットされます。マスターには常に最新の安定版リリースが含まれます。

たとえば、現在のリリースが 1.5 で、現在すべてが master の下にあり、履歴ブランチがないとします。現在の安定コードの下に線を引き、1.5 というブランチを作成します。ここで、1.5 ブランチでビルドする 1.6 で開発を開始するには、master から新しいブランチを作成し、1.6 と呼びます。

1.6 に向けた開発は、1.6 ブランチ、または 1.6 をベースとして作成された他のブランチで行われます。これは、必要に応じてすべてが適切に 1.6 ブランチに適切にプッシュ/プルできることを意味します。

1.5 リリースで小さなバグ修正を適用する必要がある場合は、1.5 ブランチで簡単に行うことができます。1.6 ブランチからコミットをプルしたい場合は、それを「チェリー ピック」する必要があります。ブランチが分岐し始めているため、「安定版」を保護するために最大の安全性を確保するために、そのような問題は手動で処理する必要があります。 "コードベース。

1.7/2.0 などを作成するときが来たら、1.6 リリースをマスターにプルし、タグを付けて、新しいバージョン用の新しいブランチを作成します。

このようにして、バージョン/リリースごとに誰がいつ何をしたかという完全な履歴がブランチに保存されます。他の人が述べたように、マイルストーン リリースにタグを付けることを忘れないでください。

ウェブサーバー

上記のアプローチでは、Web サーバーのセットアップを維持するのはかなり簡単です。各リリースのルートは、適切なブランチと単純に同期されます。

したがって、簡単にするために、バージョン管理のリポジトリのルート ディレクトリが API コードのドキュメント ルートに対応していると仮定してみましょう (実際にはそうではないかもしれませんが、URL の書き換えまたは同様のアプローチで解決できます)。これ)。

Web サーバー上のドメインのドキュメント ルートに、次のディレクトリ構造を作成します。

<ドキュメントルート>
    | |
    |--- 1.5
    | |
    |--- 1.6

1.5、1.6 の各ディレクトリに、中央のバージョン管理からリポジトリを複製し、適切なブランチに切り替えます。変更をライブにプッシュするたびに、適切なブランチのバージョン管理から変更をプルダウンするだけです。

大規模な環境では、バージョン識別子をサブドメインとして各バージョンを提供する専用のサーバー全体を使用する場合がありますが、リポジトリを各サーバーのドキュメント ルートに直接複製できることを除いて、同じ一般原則が適用されます。

新しいブランチのディレクトリを作成し、そこにリポジトリをクローンし、適切なブランチに切り替え、リリース用のパッチ/バグ修正を取得するプロセスの多く (すべてではないにしても) は、scripts/cron などを使用して自動化できますが、これを行う前に忘れないでください: 人間の関与なしにライブ サーバーに変更をプッシュすると、多くの場合、失敗に終わります。


別のアプローチ

...ドメインのドキュメント ルートとして機能する単一の親リポジトリを作成することになります。この場合、各バージョンのリポジトリのルートにサブモジュールを作成します。これが作成する全体的な効果は非常に似ていますが、サーバー上の単一のリポジトリを同期するだけで済み、バージョン管理によって定義された Web サーバーのディレクトリ構造を維持するという「利点」があります。ただし、個人的には、いくつかの理由から、このアプローチは好きではありません。

  • サブモジュールは維持するのが面倒です。それらは特定のコミットに関連付けられており、それを忘れがちです。
  • ブランチ駆動型のアプローチによって提供される制御は、より詳細で、何が起こっているかについてより明確になっていると思います。

ただし、これらの理由はどちらも主に個人的な好みであることを認めているため、可能性として取り上げています.

于 2013-06-27T13:41:30.680 に答える
2

これはばかげたハックですが、あなたが望む動作に近づいているようです。気になる 0.5.php の最初のコミットに次のようにタグを付けていることを前提としていることに注意してくださいfirst

  1. ブランチ

    % git checkout -b tmp

  2. 0.5.php ファイルのコミット履歴のパッチ フォルダーとパッチ バージョンを作成します。

    % mkdir patches && git format-patch first 0.5.php -o patches

  3. ファイルを削除し、その最初のコピーをチェックアウトします

    % rm 0.5.php && git checkout first -- 0.5.php

  4. ファイルの名前を変更する

    % mv 0.5.php 0.6.php

  5. 新しい名前を使用するようにパッチ ファイルを微調整します

    % sed 's/0\.5\.php/0\.6\.php/g' -i patches/0*

  6. commit (まだ数回行っていない場合)

    % git add -A && git commit -m'ready for history transfer'

  7. パッチを適用する

    % git am -s patches/0*

  8. マスターに戻り、新しいファイルをプルしてtmpブランチを削除します

    % git co master && git co tmp -- 0.6.php && git branch -D tmp

出来上がり!0.6.php ファイルには、0.6.php の履歴の各コミットが 0.5.php の履歴の一意の ID を持つことを除いて、0.5.php ファイルを複製する履歴があります。時間と非難はまだ正しいはずです。少し余分な努力をすれば、おそらくすべてをスクリプトに入れ、そのスクリプトを にエイリアスすることができますgit cp

于 2013-07-23T03:32:19.270 に答える
2

警告: 次のコマンドは、共有リポジトリでは望ましくないことが多い履歴を書き換えます。-f を押す前によく考えてください。

履歴を書き換えて、次のファイルの 2 番目のコピーを含めますgit filter-branch

git filter-branch --tree-filter 'if [ -f 0.5.php ]; then cp 0.5.php 0.6.php; fi' HEAD

現在、0.6.php は、すべての履歴で 0.5.php の正確な複製です。


次に、同僚が新しい履歴を処理する必要があります。

誰かがリベースまたはリセットを発行済みブランチにプッシュした後、どうすれば回復/再同期できますか?

于 2013-07-28T05:56:56.543 に答える
1

git サブツリーをチェックしてください(こちらも参照)。これにより、その 1 つのファイルで履歴の一部を分割できる必要があります。ボットがインタラクティブなリベースを使用している場合は、それを複製することもできます。次に、それをマージして、複製することができます。

于 2013-06-27T12:51:29.467 に答える