Git でのマージの操作

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-09-27 12:25:031163ブラウズ

Working with Merge in Git

今週のブログでは、git merge の使用に関するラボを終了した後の私の考えと経験を共有したいと思います。

Git マージ戦略

Git での作業に焦点を当てた最近のラボを完了した後、Git が使用する 2 つの主要なマージ戦略、つまり、早送りマージと 3 方向再帰 (recursive-ort) マージについて、より深く理解できるようになりました。

  • 早送りマージ: これは、フィーチャー ブランチが作成されてからメイン ブランチに新しいコミットがない場合に発生します。このシナリオでは、Git はメイン ブランチ ポインターをフィーチャー ブランチからの最新のコミットに単純に移動します。このタイプのマージでは個別のマージ コミットが作成されないため、単純かつ直線的になります。

  • 3 方向再帰的マージ: このアプローチは、メイン ブランチとフィーチャー ブランチの両方に分岐するコミットがある場合に使用されます。 Git は共通の祖先を計算し、両方のブランチからの変更をマージしようとします。両方のブランチの同じ行またはファイルに変更が加えられた場合、競合が発生する可能性があり、手動で解決する必要があります。当初、私は異なるブランチ間で同じファイルを変更すると常に競合が発生するという印象を持っていました。ただし、競合が発生するのは、両方のブランチでまったく同じコード行が変更された場合のみです。

ラボ実装: 機能ブランチのマージ

このラボでは、リポジトリ VShell に 2 つの機能を追加することに取り組みました。これには、機能ごとに個別のブランチを作成することが含まれていました。これらの機能は、複数の入力ファイル/フォルダーとストリーミング出力をサポートすることでツールの機能を向上させるように設計されました。

機能 1: 複数のファイルとフォルダーのサポート - 問題 15:

最初の機能には、ツールが複数のファイルとフォルダー パスを同時に処理できるようにすることが含まれていました。以前は、このツールは個々のファイル入力のみを処理していましたが、この機能強化により、ユーザーは複数のファイルまたはディレクトリを引数として渡すことができるようになりました。ディレクトリ内のすべてのファイルが処理されます。

これを実装するために、フォルダーの内容を再帰的に反復処理し、ファイル パスを絶対パスに変換し、関連するすべてのファイルを配列に保存するように既存のロジックを拡張しました。関連するスニペット:

files.forEach((file) => {
    // convert a file path to an absolute path
const filePath = path.resolve(file);
...
const directoryFiles = fs
          .readdirSync(filePath)
          .map((f) => path.join(filePath, f));
allFiles = allFiles.concat(directoryFiles);
...
const results = allFiles.map((file) => {
    process.stderr.write(`Debug: Processing file: ${file}. \n`);
    return fs.readFileSync(file, "utf-8");
});
return results.join("\n");
}

このコードは、個々のファイルとディレクトリ内のすべてのファイルの両方が適切に処理されることを保証します。

機能 2: 標準出力へのストリーミング応答 - 問題 16:

2 番目の機能では、ストリーミング サポートがツールに追加され、-s/--stream フラグを使用して stdout への応答のリアルタイム出力が可能になりました。これは、応答が出力ファイルに書き込まれるか、処理が完了すると完全に表示されるだけだった以前の実装に比べて大幅に改善されました。

これを実現するために、for await...of ループを使用して、ストリーミングされるデータ チャンクを処理する非同期反復を導入しました。さらに、トークン情報は最終応答チャンクでのみ利用できるため、トークンの使用状況をリアルタイムで追跡しました。コアロジックは次のとおりです:

if (options.stream) {
// Handle streaming response
const { response, tokenInfo } = await readStream(chatCompletion);
return { response, tokenInfo };
}
async function readStream(stream) {
  let response = "";
  let tokenInfo;
  for await (const chunk of stream) {
    const content = chunk.choices[0]?.delta?.content;
    if (content) {
      process.stdout.write(content);
      response += content;
    }
    // The last chunk will contain the usage information
    if (chunk?.x_groq?.usage) {
      // Retrieve Token Usage from Response
      const usage = chunk?.x_groq?.usage;
      const promptToken = usage?.prompt_tokens || 0;
      const completionToken = usage?.completion_tokens || 0;
      const totalToken = usage?.total_tokens || 0;
      tokenInfo = { promptToken, completionToken, totalToken };
    }
  }
  return { response, tokenInfo };
}

注:

リアルタイム ストリーミング アプローチでは、使用状況データに直接アクセスできる非ストリーミング応答に使用される単純な方法とは対照的に、トークン追跡の調整が必要でした。

ストリーミングの場合、トークン使用オブジェクトはループ内の最後のチャンクを処理した後にのみアクセスできます。

// The last chunk will contain the usage information
if (chunk?.x_groq?.usage) {
  // Retrieve Token Usage from Response
  const usage = chunk?.x_groq?.usage;
  ...
}

デフォルトでは、-o/--output で出力ファイルを指定せずに -s/--stream フラグを使用すると、応答はストリーミングされ、リアルタイムでコンソールに表示されます。ただし、ユーザーが応答をファイルにエクスポートしたい場合は、-o/--output フラグを使用して出力ファイルを指定できます。

マージプロセスと Git マージ戦略

両方の機能を完了した後、マージ プロセスを開始し、まず機能 1 をメイン ブランチにマージし、続いて機能 2 をマージしました。機能は別のファイルで開発されたため、マージ プロセス中に競合は発生しませんでした。ただし、Git は、Git 2.34 以降のデフォルトである ORT マージ戦略 (表向きは Recursive の Twin) を使用しました。 ORT 戦略は、古典的な再帰的マージ戦略を書き直したもので、複雑なマージ シナリオを処理する際のパフォーマンスと精度が向上します。

私の最終的なマージコミットハッシュは: 286e23c

以上がGit でのマージの操作の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。