Contents

Controlled examples on real repositories

Three popular open-source projects, two agents in each, two reasonable changes. Plain Git merges every pair without a conflict. The merged code then crashes, fails to build, or quietly does the wrong thing.

The projects are unmodified copies of psf/requests, sindresorhus/ky and go-chi/chi from their main branches in October 2026. The changes are ours, made for this page and written the way an agent would write them, so these are controlled examples, not incidents from production.

ProjectPlain GitAfter the mergegitta
requests (Python)Merges, no conflictCrashes at run timeWarns the agent during the work
ky (TypeScript)Merges, no conflictThe build failsWarns the agent during the work
chi (Go)Merges, no conflictWrong value, no errorWarns the agent during the work

requests, the Python HTTP library, where a helper now returns nothing

One agent follows RFC 7231 and removes the old ISO-8859-1 default for text responses without a charset. get_encoding_from_headers now returns None for them. Its own change is correct.

  # src/requests/utils.py, agent no-latin1-default
-    if "text" in content_type:
-        return "ISO-8859-1"
-

At the same time, another agent adds a debug helper that calls the same function and expects a string.

# src/requests/diagnostics.py, agent encoding-log (new file)
from .utils import get_encoding_from_headers


def describe_encoding(response):
    """One line for the debug log: which encoding the body will be decoded with."""
    return "body encoding: " + get_encoding_from_headers(response.headers).lower()

Plain Git merges both. The first text/html response without a charset then crashes the helper:

 After a plain git merge
AttributeError: 'NoneType' object has no attribute 'lower'

With gitta, the second agent hears about it in its session, before it finishes:

 In the encoding-log agent's session
Gitta: agent no-latin1-default changed `get_encoding_from_headers`, which your new code in src/requests/diagnostics.py calls. Check that your code still fits. Their version: src/requests/utils.py:569: def get_encoding_from_headers(headers: CaseInsensitiveDict[str]) -> str | None:

Handle it yourself and tell the user in one sentence.

The agent makes its helper handle a missing encoding. When you merge, gitta runs your tests on the combined code, so a test that covers this case stops the merge before main changes.

ky, the TypeScript HTTP client: a field renamed for clarity

One agent renames the timeout field of the shared TimeoutOptions type to timeoutMs, so the unit is obvious. It updates every place that uses the field, and its build passes.

  // source/utils/timeout.ts, agent timeout-ms
 export type TimeoutOptions = {
-	timeout: number;
+	/** Milliseconds. */
+	timeoutMs: number;

Another agent adds a longer deadline for uploads, written against the old field name. Its build passes too.

// source/utils/deadline.ts, agent upload-deadline (new file)
import type {TimeoutOptions} from './timeout.js';

/** Uploads get a longer deadline than ordinary requests. */
export const uploadTimeoutOptions = (fetch: TimeoutOptions['fetch']): TimeoutOptions => ({
	timeout: 120_000,
	fetch,
});

Plain Git merges both. The merged code no longer compiles:

 tsc after a plain git merge
source/utils/deadline.ts(5,2): error TS2561: Object literal may only specify known properties, but 'timeout' does not exist in type 'TimeoutOptions'. Did you mean to write 'timeoutMs'?

CI would catch this one after the merge. gitta catches it while the second agent still works on the file:

 Terminal
$ gitta status
main is the branch gitta merges finished work into.
  timeout-ms 2 files changed, ready to merge
  upload-deadline 1 file changed, ready to merge
  timeout-ms changed `source/utils/timeout.TimeoutOptions`, which upload-deadline's new code in source/utils/deadline.ts uses. Check that the two changes still work together.

With a gate that builds the code, such as npm test, git merge stops on this build error before main moves.

chi, the Go router: shorter request IDs

One agent makes logs easier to read. GetReqID now returns only the counter of a request ID, for example 000042 instead of web-3/a1b2c3-000042. It updates the test that checks the ID, and its tests pass.

  // middleware/request_id.go, agent short-request-ids
 	if reqID, ok := ctx.Value(RequestIDKey).(string); ok {
+		// Logs only need the counter: "host/abc123-000042" becomes "000042".
+		if i := strings.LastIndex(reqID, "-"); i >= 0 {
+			return reqID[i+1:]
+		}
 		return reqID
 	}

Another agent adds middleware that tells clients which host served them, read from the start of the same ID.

// middleware/served_by.go, agent host-header (new file)
func ServedBy(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		host := strings.SplitN(GetReqID(r.Context()), "/", 2)[0]
		w.Header().Set("X-Served-By", host)
		next.ServeHTTP(w, r)
	})
}

Plain Git merges both. The code compiles and nothing crashes. The header is simply wrong:

 go test after a plain git merge
--- FAIL: TestServedByExample (0.00s)
    zz_served_by_example_test.go:16: X-Served-By = "000042", want "web-3"

Only a test for exactly this case finds it. With gitta:

 In the host-header agent's session
Gitta: agent short-request-ids changed `GetReqID`, which your new code in middleware/served_by.go calls. Check that your code still fits. Their version: middleware/request_id.go:83: func GetReqID(ctx context.Context) string {

Handle it yourself and tell the user in one sentence.

The agent reads the new definition and takes the host from somewhere else. At merge time your tests on the combined code decide, as in the other two cases.

What the three have in common

Each change is reasonable alone, and each agent's own checks pass. The problem exists only in the combination, so neither agent can see it and plain Git cannot either. gitta compares what each agent changed with what each other agent's new code uses, while they work. The second agent learns about the change in time to adapt, instead of after the merge.

To try it in your own repository, follow the quick start. Measurements shows how gitta did with real agents.