git fetch-pack pulls objects from a remote and stores them locally, then stops, leaving your branches untouched. It is the plumbing underneath git fetch. You will fetch one remote branch into a disposable test repository, verify the object actually arrived, and see first-hand why nothing moves until you tell it to.
git-man documentation.Confirm which Git you are running, then read its local synopsis rather than trusting memory:
$ git --version
$ git fetch-pack -h
On the machine used for this guide, that prints git version 2.43.0. The installed synopsis takes a repository followed by optional remote refs, with options such as --all, --keep, --thin, --include-tag, --depth and --no-progress. Work in a throwaway clone: the command writes objects straight into the current repository's object database, so do not point it at anything you would miss.
Checkpoint: if the version here is not the one you meant to test, stop. Options drift between Git releases, so check that release's manual before copying an example.
Run the command from the destination repository. The repository argument can be a local path, an SSH-style location, or any other URL Git accepts. A ref such as refs/heads/main is relative to the remote's own ref namespace, not yours:
$ cd /path/to/destination-repository
$ git fetch-pack /path/to/remote-repository.git refs/heads/main
A successful run prints the object name and the ref it received:
eda5d8f6c0c87f17de79eb376dc408602d50df63 refs/heads/main
Your object name will differ; capture it if a script needs to act on the result. The command negotiates against commits already reachable from your local refs/ hierarchy, so if the two repositories share no common ancestor, expect a bigger download than you might guess.
Use the object name from the output, or the same commit resolved in a trusted copy of the remote, to confirm it landed:
$ git cat-file -t OBJECT_NAME_FROM_THE_OUTPUT
commit
Replace OBJECT_NAME_FROM_THE_OUTPUT with the 40-character ID your run printed. The object now exists in your object database, which is not the same as a branch having moved:
$ git show-ref
$ git rev-parse --verify refs/heads/main
The second command can fail with fatal: Needed a single revision if you did not already have a local main. That is expected, not broken: fetch-pack receives objects and reports remote refs, full stop. It is not the ref-updating workflow you get from a normal fetch.
Checkpoint: if all you actually wanted was an updated branch, stop reaching for fetch-pack and run git fetch REMOTE REFSpec instead. Keep using this lower-level command only when you deliberately need it, and only update a ref afterwards once you have inspected the returned object against your repository's policy.
--all. This can pull down considerably more data than a named ref, and it still only reports refs; it does not set up the usual local remote-tracking refs.$ git fetch-pack --all /path/to/remote-repository.git
$ git fetch-pack /path/to/remote-repository.git refs/heads/main refs/tags/v1.2.3
Leave the ref list empty and, per the manual, the command updates from every head the remote has. Treat that as a broad transfer request, not as permission for Git to create or update every matching local ref on its own.
--depth=N limits fetched history to ancestor chains no longer than N commits. This creates or extends a shallow repository and can affect later operations that need older ancestry.--deepen-relative extends an already-shallow repository by counting depth from the existing shallow boundary rather than from each remote tip. The installed 2.43.0 manual also documents --shallow-since, --shallow-exclude and --refetch for more specific shallow or partial-clone needs.--keep stores the received data as one pack instead of running git unpack-objects. Pass it twice and the pack is locked against repacking, useful for a carefully managed transfer, but it changes pack maintenance and eats disk space.--thin cuts network traffic by allowing deltas based on objects you already have locally. It depends on the receiver actually having those base objects.$ git fetch-pack --depth=20 /path/to/remote-repository.git refs/heads/main
PATH. Use --upload-pack=/absolute/path/to/git-upload-pack when the remote Git installation sits outside its service path, and confirm that path with the remote administrator first.--all, and an empty ref list, are both broad requests by design.git cat-file instead. This is normal for fetch-pack; reach for git fetch when you actually need remote-tracking refs and ordinary fetch behaviour.--no-progress. Add --quiet only once you have another way to record failures and results.Recovery: there is no general undo for received objects. Unreferenced objects eventually become eligible for Git's own housekeeping, but do not force a prune just to reverse a test: pruning can take other unreachable work with it. If you built the destination purely for this exercise, discard that disposable repository through your normal, separately checked cleanup procedure.
git cat-file -t.git fetch instead whenever an ordinary ref update was the actual goal.