git-graft
Manually define parent commits for initial history
TLDR
Merge all commits not present on the target branch from the source branch to target branch, and delete the source branch
SYNOPSIS
Note: git-graft is not a standalone command. This section describes the format of the deprecated .git/info/grafts file, which implemented the grafting functionality.
.git/info/grafts
Each line in this file specifies a graft, formatted as:
commit_id parent_id ...
PARAMETERS
commit_id
The 40-character SHA-1 hash of the commit whose parents are to be overridden by the graft.
parent_id ...
One or more 40-character SHA-1 hashes representing the new parent(s) for the specified commit_id. If multiple parents are provided, the commit is treated as a merge commit with these new parents. If no parent_id is given, the commit becomes a root commit.
DESCRIPTION
The term git-graft refers to a historical and now deprecated mechanism in Git for locally altering the parent pointers of existing commits without actually rewriting their SHA-1 hashes. This functionality was primarily managed through the .git/info/grafts file within a repository. By adding lines to this file, users could effectively "graft" a commit onto a different parent in the commit graph, making it appear as if that commit had a different history in the local repository. This was useful for tasks such as connecting disconnected histories, fixing broken merges, or temporarily visualizing an alternative commit lineage.
Unlike powerful history rewriting tools like git filter-branch or git filter-repo, which permanently alter commit objects and their hashes, grafting only provided a superficial, local view change. This made it unsuitable for pushing such changes to shared repositories. Due to its limitations and the introduction of more robust and flexible alternatives, particularly git replace, the .git/info/grafts file and the "graft" concept it represented were deprecated in Git versions 1.6.5 and later.
CAVEATS
git-graft (and the underlying .git/info/grafts mechanism) comes with significant caveats:
Deprecated: The .git/info/grafts file was deprecated in Git v1.6.5 and is no longer recommended for use. Modern Git versions might not fully support or might ignore it.
Local-Only Effect: Grafts only affect the local repository where the .git/info/grafts file resides. They are not part of the repository's permanent history and cannot be pushed or pulled to other repositories.
No History Rewrite: Unlike tools that rewrite history (e.g., git filter-branch), grafting does not change the actual commit objects or their SHA-1 hashes. It merely instructs Git to locally consider a commit as having different parents.
Superseded: The functionality provided by grafting has been largely superseded by git replace for similar temporary, local history modifications, and by history rewriting tools for permanent changes.
LIMITATIONS
Beyond its deprecated status and local-only nature, the .git/info/grafts mechanism had other limitations. It could become difficult to manage in complex scenarios and provided no inherent way to remove a graft other than manually editing the file. Furthermore, the changes were purely symbolic; Git commands like git log would respect the grafts, but fundamental operations that traverse actual commit objects (e.g., when cloning a shallow repository or certain types of git fsck checks) might behave unexpectedly or ignore the grafts, as the underlying commit objects remained unchanged.
HISTORY
The concept of "grafting" in Git originated with the .git/info/grafts file, providing an early and simple mechanism for users to manipulate the perceived parentage of commits locally. This file was introduced to address scenarios where repository history needed adjustment without the complexity and performance overhead of a full history rewrite. However, its significant limitation was the local-only nature of the changes, preventing their propagation to other repositories.
As Git evolved, the need for more robust and shareable history manipulation became apparent. This led to the development of tools like git filter-branch, capable of truly rewriting history by creating new commit objects. For the specific use case of locally "faking" history, the more flexible and programmatic git replace command was introduced, providing a superior alternative to the manual .git/info/grafts file. Consequently, the .git/info/grafts mechanism was officially deprecated in Git v1.6.5, encouraging users to adopt git replace for similar local effects or dedicated history rewriting tools for permanent changes.
SEE ALSO
git-replace(1), git-filter-branch(1), git-rebase(1), git-cherry-pick(1), git filter-repo