Diff
Pitmaster menghitung diff dalam format unified milik git. Mesin diff mendukung beberapa algoritma, pemformatan unified diff, deteksi file biner, dan perbandingan rekursif tingkat tree.
Untuk file teks yang dimodifikasi dengan mode 100644, format() menghasilkan byte yang sama dengan git diff. Kasus lainnya saat ini diformat secara berbeda (#3):
- File baru dan yang dihapus tidak memiliki baris
new file mode/deleted file mode, barisindex, ataupun/dev/null: kedua sisi diberi labela/<path>danb/<path>, dan rentang hunk sisi kosong ditulis sebagai-1,0atau+1,0, sementara git menulis-0,0atau+0,0. - Baris
indexselalu diakhiri dengan100644, apa pun mode filenya. - Perubahan mode saja (misalnya
chmod +x) tidak menghasilkan apa pun. - File biner menampilkan
Binary files differtanpa barisindex, sedangkan git menampilkanBinary files a/<path> and b/<path> differ. - Penggantian nama ditampilkan sebagai satu entri
diff --git a/<old> b/<new>dengan diff konten, tanpa barissimilarity index,rename from, ataurename to.
Operasi diff
Perubahan yang belum di-stage (worktree vs index)
$diffs = $repo->diff();
foreach ($diffs as $diff) {
echo $diff->format();
}
Membandingkan setiap file dalam index dengan kondisinya saat ini di working tree. Mendeteksi modifikasi, penghapusan, dan file biner.
Perubahan yang sudah di-stage (index vs HEAD)
$diffs = $repo->diffStaged();
foreach ($diffs as $diff) {
echo $diff->format();
}
Membandingkan index saat ini dengan tree commit HEAD. Menampilkan apa yang akan disertakan dalam commit berikutnya. File yang dihapus dan ditambahkan dengan konten serupa dilaporkan sebagai satu entri yang diganti namanya. Sebelum commit pertama, HEAD belum ada dan hasilnya kosong (#5).
Pemasangan pasangan nama saat ini juga mencocokkan file satu baris yang tidak berkaitan, karena baris kosong di akhir dihitung sebagai konten yang sama (#4).
Diff antar-tree
$a = $repo->readObject($repo->resolve('HEAD~1')->hex)->tree;
$b = $repo->head()->tree;
$diffs = $repo->diffTree($a, $b);
Membandingkan dua tree secara rekursif. Berikan ID tree: ID commit tidak diurai menjadi tree-nya dan akan menghasilkan hasil kosong. Mesin TreeDiff yang sama digunakan oleh diffStaged(), show(), dan logPath().
Filter berdasarkan jalur
$diffs = $repo->diff('src/specific-file.php');
Spesifikasi jalur adalah satu jalur file yang persis. diffStaged() menerima argumen yang sama tetapi untuk saat ini mengabaikannya, jadi selalu mengembalikan setiap file yang sudah di-stage (#5).
Pilih algoritma
$diffs = $repo->diff(null, 'patience');
$diffs = $repo->diffStaged(null, 'histogram');
$diffs = $repo->diffTree($a, $b, 'minimal');
Nama yang valid adalah myers (default), patience, histogram, dan minimal. Nama lainnya akan melempar InvalidArgumentException.
Struktur DiffResult
Setiap DiffResult merepresentasikan diff untuk satu file.
use Pitmaster\Diff\DiffResult;
foreach ($diffs as $diff) {
echo $diff->oldPath; // Path in the old tree
echo $diff->newPath; // Path in the new tree
echo $diff->binary; // true for binary files
echo $diff->oldHash; // Hex hash of the old blob (null for added files)
echo $diff->newHash; // Hex hash of the new blob (null for deleted files)
foreach ($diff->hunks as $hunk) {
echo $hunk->header(); // @@ -1,5 +1,7 @@
foreach ($hunk->lines as $line) {
echo $line . "\n"; // ' context', '+added', '-removed'
}
}
}
Output berformat
echo $diff->format();
Menghasilkan output unified diff. Untuk file teks yang dimodifikasi, hasilnya cocok dengan git diff:
diff --git a/src/File.php b/src/File.php
index abc1234..def5678 100644
--- a/src/File.php
+++ b/src/File.php
@@ -10,6 +10,8 @@ class File
private string $name;
+ private int $count;
+
public function __construct()
{
Periksa perubahan
if ($diff->hasChanges()) {
// File was modified (or is binary with changes)
}
Struktur hunk
Setiap Hunk merepresentasikan bagian perubahan yang berurutan beserta baris konteks.
use Pitmaster\Diff\Hunk;
$hunk->oldStart; // Starting line in old file
$hunk->oldCount; // Number of lines from old file
$hunk->newStart; // Starting line in new file
$hunk->newCount; // Number of lines in new file
$hunk->lines; // Array of diff lines (prefixed with ' ', '+', or '-')
$hunk->header(); // "@@ -10,6 +10,8 @@"
Algoritma diff
Pitmaster menerapkan empat algoritma diff. Default-nya adalah Myers.
Diff Myers
Algoritma O(ND) standar, sama seperti default git. Menghasilkan skrip edit minimal.
use Pitmaster\Diff\MyersDiff;
$hunks = MyersDiff::diff($oldContent, $newContent);
Metode diff() menerima dua string dan mengembalikan array berisi objek Hunk. Metode ini membagi input berdasarkan baris baru, menghitung skrip edit terpendek, dan mengelompokkan perubahan menjadi hunk dengan 3 baris konteks (sesuai default git).
Diff Patience
Diff struktural yang lebih baik untuk kode. Mencocokkan baris unik terlebih dahulu, lalu mengisi bagian di antaranya.
use Pitmaster\Diff\PatienceDiff;
$hunks = PatienceDiff::diff($oldContent, $newContent);
Diff Histogram
Varian diff patience yang lebih baik dalam menangani baris berulang. Digunakan oleh JGit dan Eclipse.
use Pitmaster\Diff\HistogramDiff;
$hunks = HistogramDiff::diff($oldContent, $newContent);
Diff Minimal
Menghasilkan diff sekecil mungkin (jumlah baris yang berubah paling sedikit), dengan konsekuensi komputasi yang lebih banyak.
use Pitmaster\Diff\MinimalDiff;
$hunks = MinimalDiff::diff($oldContent, $newContent);
Deteksi biner
Pitmaster memperlakukan konten sebagai biner jika byte NUL terdapat di antara 8192 byte pertama (git memeriksa 8000 byte pertama).
if (MyersDiff::isBinary($content)) {
// Binary file, skip line-level diff
}
File biner menghasilkan DiffResult dengan $binary = true dan array $hunks kosong. Output berformatnya adalah:
diff --git a/image.png b/image.png
Binary files differ
Output berwarna
CLI menggunakan ColorDiff untuk output terminal dengan warna ANSI.
use Pitmaster\Diff\ColorDiff;
$colorized = ColorDiff::colorize($diff->format());
echo $colorized;
- Baris yang ditambahkan (
+) ditampilkan dalam warna hijau - Baris yang dihapus (
-) ditampilkan dalam warna merah - Header hunk (
@@) ditampilkan dalam warna sian - Header file (
diff --git,index,---,+++) ditampilkan dengan huruf tebal
pitmaster diff selalu memberi warna, termasuk saat output-nya dialirkan melalui pipe. pitmaster show hanya memberi warna saat stdout berupa terminal.
Perbedaan tree (internal)
Kelas TreeDiff membandingkan dua objek tree secara rekursif dan menghasilkan DiffResult untuk setiap file yang berubah.
use Pitmaster\Diff\TreeDiff;
$treeDiff = new TreeDiff($repo->objectDatabase());
$diffs = $treeDiff->diff($oldTreeId, $newTreeId);
Perbedaan tree menangani:
- File yang ditambahkan (hanya ada di tree baru)
- File yang dihapus (hanya ada di tree lama)
- File yang diubah (path sama, hash blob berbeda)
- Perbandingan subdirektori secara rekursif
- Pemasangan pasangan file yang diubah namanya antara file yang dihapus dan ditambahkan (hash persis sama, atau setidaknya 50% baris yang sama)
Entri dengan hash yang tidak berubah akan dilewati, jadi perubahan mode saja tidak menghasilkan hasil.
Perbedaan kata
Untuk perubahan sebaris pada tingkat kata di dalam baris.
use Pitmaster\Diff\WordDiff;
$result = WordDiff::diff('the quick fox', 'the slow fox');
// 'the [-quick-]{+slow+} fox'