Linhas com < vêm do primeiro arquivo do comando (a versão velha); linhas com >, do segundo (a nova). As linhas iguais nas duas não aparecem.
Cada bloco começa com um cabeçalho que diz o que aconteceu e onde. 2c2: a linha 2 mudou (change), e o bloco mostra a velha e a nova. 4d3: a linha 4 foi apagada (delete). 5a5: depois da linha 5 da velha, foi acrescentada (add) a linha 5 da nova.
Uma linha que só mudou de lugar aparece duas vezes: como < num bloco d, onde estava, e como > num bloco a, onde foi parar. Para ter certeza de que algo sumiu, procure no arquivo novo: grep Dora terca.txt.
O diff ignora as linhas iguais e mostra só as diferentes: a linha de Bento mudou (c) e aparece com < e >, a de Dora foi apagada (d) e só tem <, a de Fabi foi acrescentada (a) e só tem >.
Outros formatos do mesmo comando:
diff -u velho novo usa - e + e mostra umas linhas de contexto em volta; é o formato do git e dos patches.
diff -y velho novo mostra lado a lado (junte --suppress-common-lines para esconder as iguais).
diff -q pasta1 pasta2 só diz quais arquivos diferem, e diff -r pasta1 pasta2 compara pastas inteiras.
Quando o diff não mostra nada, os arquivos são idênticos. Em Python, difflib.unified_diff(velho.splitlines(), novo.splitlines()) gera a mesma comparação no formato -u.