1
  1. Does a linear commit history exist for any branch head in a git repository, all the way back to an empty git repo? Essentially a list of commits in its history, whose diffs when applied in order can get the empty repo to current state of the branch?
  2. Is there "git format-patch" command that can extract that linear commit history
  3. Specifically, that extracted series of patches should should be usable in with a "git init ; git am patches.txt" to reconstruct the latest branch head state, without running into patch conflicts

Even if it means a bit of scripting to achieve what I want above.

----- Question as asked initially --------

I have a git repoA and checked out say branch branchX

I want to generate a sequence of patches with "git format-patch" that i can use to rebuild a brand new git repo using "git am/apply" from scratch(git init) with just that one branchX and its complete history going back to commit zero.

Currently I tried getting the patch as follows from repoA

git --no-pager format-patch --binary --stdout --root branchX > patch.list OR # f7ef86f26066fb428305f3809309ba33d70a9feb is considered the zero/empty state/commit of any git repo git --no-pager format-patch --binary --stdout --root f7ef86f26066fb428305f3809309ba33d70a9feb branchX > patch.list cd /path/to/repoNew git init git am --3way patch.list OR git am patch.list 

But some how the patch.list generated by above format-patch command

bash-4.2$ git am --3way /witspace/sarvi/space_sarvi_mynxos/kwaiclean/boot/t Applying: Initial branch reference point created applying to an empty history Applying: Admin created refpoint (likely to handle manual repository mucking) Applying: new-module-makes Applying: new-module-makes Applying: new file for sienna target Applying: change the rule for specifying EXTRA_* Applying: Removing Makefile.am files and modifying copyright entry Applying: changes for bringing up isan-image on maui Applying: Adding group 'routing-sw' to /etc/group. The routing-sw components will be started by sysmgr in process group 'routing-sw'. This will allow us to kill/ restart all routing-sw components without rebooting Linux/SANOS. Applying: added a new dhcpd.conf file that is specific to 13-slot Applying: modify the /etc/dhcpd.conf in each lc-line entry to specifiy the slot number as part of creating DHCP links to correct LCImage Applying: Update build infrastructure for DC3 builds Applying: Use our own passwd/group files instead of using the one in basefs Using index info to reconstruct a base tree... M aci/bootglobalpkg/group .git/rebase-apply/patch:34: new blank line at EOF. + warning: 1 line adds whitespace errors. Falling back to patching base and 3-way merge... Auto-merging aci/bootglobalpkg/group Applying: Changes for preparation of new restructure of workspace Applying: DC-OS Codebase Restructure: Stage1 + Stage2 for branch sf Using index info to reconstruct a base tree... M aci/bootbios_program/module.mk Falling back to patching base and 3-way merge... Auto-merging aci/bootbios_program/module.mk CONFLICT (content): Merge conflict in aci/bootbios_program/module.mk error: Failed to merge in the changes. Patch failed at 0015 DC-OS Codebase Restructure: Stage1 + Stage2 for branch sf hint: Use 'git am --show-current-patch=diff' to see the failed patch When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". bash-4.2$ 

What I am not getting is if "git format-patch" command, above does get/generates all the commits/patches from initialization of the source/original git repo, in the right order, and the "git am" command only applies them in that same sequence, why would there be conflicts?

How do do this right ?

Why is it not possible to start with a branch head, walk linearly to the first commit and get the sequence of patches in order and apply them in a branch new git repo to reproduce that linear history through patches.

13
  • Just a wild guess: Do you have files with CRLF line endings instead of LF? Then you should add --keep-cr to the git am command. Commented Dec 6, 2021 at 6:30
  • tried that. doest seem to be helping Commented Dec 6, 2021 at 6:40
  • 2
    Commits, in a Git repository, form a Directed Acyclic Graph (DAG). The format-patch walks part of the DAG, producing a linear representation in which merge commits are discarded; non-empty non-merge commits are converted from snapshot-and-metadata to text-and-diff. The resulting diffs form purely linear chains, from which the original DAG cannot be recovered as the merges have been discarded. Commented Dec 6, 2021 at 6:58
  • 1
    In short, you're trying to do something that cannot and should not be tried. Commented Dec 6, 2021 at 6:58
  • If git is a DAG, then it should be possible to walked from a branch head to the original empty git repo state aka first commit, then why is it not possible as a sequence of incremental commits/changes, to get a sequence of diffs or patches that can be used to rebuild just that linear history without any conflicts ? That doest seem to make sense to me Commented Dec 6, 2021 at 7:13

1 Answer 1

1
git push path/to/new/repo branchX 

will do it if you have a path to the new repo from the old, or sub in a url for the path if it's hosted somewhere reachable. Otherwise

git bundle create my.bundle branchX # get my.bundle to the destination system somehow, then in your new repo git fetch my.bundle branchX 

I want to generate a sequence of patches with "git format-patch" that i can use to rebuild a brand new git repo using "git am/apply" from scratch(git init) with just that one branchX and its complete history going back to commit zero.

That's the wrong tool for this job. As @torek points out, format-patch is built for patch-series work, communicating linear history.

Sign up to request clarification or add additional context in comments.

8 Comments

we are trying to combine 2 different component repo trees into one tree with 2 subdirectory compA and compB at its root. Towards this we are using got format-patch --src-prefix=a/compA --prefix=a/compB to generate the line series of patch from the compA/ and compA/ git repositories with the above prefix options I am reallly looking for a way to translate branchX into a series of patches that can result in the current state of branchX.
filter-branch and read-tree were built for that. format-patch was really not. How were you planning to match up commit ancestries when you have two different non-linear histories?
to be very clear: you can do what you're trying to do with Git, just not the way you're trying to do it. Sure, if Git didn't already have vastly better tools for doing what you want, the one you're trying to use might have been goosed until it could be bludgeoned into service, but when you've got a screwdriver on the wall, insistently trying to make your awl drive screws is just senseless.
What tools would be the right ones to use if I wanted to do the following 1. take 2 git repos compA and compB, that have commits in them were made together in a co-ordinated fashion 2. turn it into 1 git repo with subdirectories compA/ and compB/ init 3. During the process, I want to take those co-ordinated commits from compA and compB, that happenned and combine them into a single commit acrosa compA and compB in the new repo> What i was trying to generate a sequence patches with format-patch and "prefix" and apply them from compA and. compB
No, those are questions based on pre-conceived notions that would be very easy to correct if you'd do as I suggest and put anonymized versions if your history up so there's something concrete to talk about.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.