# sha256convert: use SetEncodedObject; rename --sign to --sign-mode

`e7e4a1a`→[main](/content/gh/entireio/git-sync/commits/main/index.html)·

nodo·1mo ago·4 files·+127 added/-182 removed

Address PR #66 review comments from @pjbgf.

go-git v6.0.0-alpha.4 (commit 5cab3a7) made objfile.Writer derive the
hash format from the store config, so the SHA1-hardcoding that forced
the hand-rolled loose-object writer is gone. Translated objects now go
through dst.NewEncodedObject + SetEncodedObject, which binds each object
to the target store's SHA256 hasher — the returned hash and the on-disk
loose path are both SHA256. Drops encodeBody/writeLoose and the manual
zlib/tempfile/rename plumbing; the on-disk sha256(content) invariant
test is kept as a regression guard.

Replace the --sign bool with --sign-mode {none,tips} (default none),
forward-compatible with a future "all" mode that signs every commit/tag.
Run validates the value up front.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

## Sessions

fec9df19e265View transcript

## Changes

4

- cmd/git-sync

- Mconvert_sha256.go+2/-2

- internal/sha256convert

- Msha256convert.go+93/-155

- Msha256convert_test.go+15/-15

- docs

- Mconvert-sha256.md+17/-10

```go
87 unmodified lines
```

```go
cmd.Flags().BoolVar(&req.Check, "check", false,
	"verify the output after conversion (config, HEAD, refs, git fsck --full)")
cmd.Flags().BoolVar(&req.Sign, "sign", false,
	"after conversion, sign each branch tip as refs/tags/converted/<branch> via `git tag -s`")
cmd.Flags().StringVar(&req.SignMode, "sign-mode", sha256convert.SignModeNone,
	"post-conversion signing: `none` (default), or `tips` to sign each branch tip as refs/tags/converted/<branch> via `git tag -s`")
cmd.Flags().StringVar(&req.SignKey, "sign-key", "",
	"signing key id to pass to `git tag -s -u`; default uses the repo's user.signingkey")
cmd.Flags().BoolVar(&req.KeepSourceObjects, "keep-source-objects", false,
```

// other content removed

### Branch-tip attestation tags (opt in via `--sign`)

`--sign` shells out to `git tag -s converted/<branch> <tip>` for every

`--sign-mode` defaults to `none` (sign nothing). `--sign-mode tips`
shells out to `git tag -s converted/<branch> <tip>` for every
converted branch after the conversion completes. Each resulting
signed annotated tag is a cryptographic attestation by the converter
that the entire reachable history of that branch — every parent, tree,

--no-rewrite-messages              skip inline hash rewrites in messages
--no-origin-notes                  skip refs/notes/sha1-origin
--check                            verify the output (config, HEAD, refs, git fsck)
--sign                             sign each branch tip via `git tag -s converted/<branch>`
--sign-mode                        signing mode: none (default) or tips
                                   (sign each branch tip as
                                   refs/tags/converted/<branch> via `git tag -s`)
--sign-key                         signing key id passed to `git tag -s -u <key>`
--keep-source-objects              leave the temp SHA1 store on disk
--progress                         live per-phase object counts (TTY only)

Loose object writing is done by hand rather than via go-git's
`SetEncodedObject`. The underlying `plumbing/format/objfile.Writer`
in `go-git/v6@v6.0.0-alpha.3` hardcodes SHA1 in its hasher, which
would put every translated object at a SHA1-derived path even though
the content references SHA256. A unit test recomputes `sha256` of
every loose object's decompressed content and compares against the
filename to prevent regression. Translated objects are written with
go-git's `SetEncodedObject`. Each one is built through the target store's
`NewEncodedObject`, which binds it to the store's SHA256 hasher, so both
the returned hash and the on-disk loose path are computed under SHA256.
