Steve Summit
Steve Summit

Reputation: 48023

trying to hook up git-p4 branches properly

I'm importing multiple branches from Perforce into git using git-p4, with full history, and it's working well, except that the various branches all end up "tailless". I know exactly at which revision (both as a Perforce changelist number and now as a newly-created git revision) each of them was branched off of the main trunk, and I'd very much like to have this explicitly reflected in my new git repository, but I can't seem to figure out how to achieve it.

Specifically, after importing, if I do a git log on any of my branches, it's always got a "last" (earliest) revision that has no parent. I'd like to rig it up so that revision has a parent which is a particular revision along master.

Presumably I can't just nakedly splice a branch onto master (i.e, simply set its parent link), because git hashes reflect full history, so all the hashes along my branch are likely to need adjusting, and I'm okay with that. I probably need a rebase operation of some kind, but again, I can't seem to figure out how to do it. The things I've tried so far have all tried to "replay" changes, as if to create slightly different versions of everything, and they've led to lots of merge conflicts which I don't have time to and don't want to resolve. The contents of each revision are perfectly fine (as created by git-p4); all I want to do is rejigger the way they're linked together.

Specifically, I want to change this:

enter image description here

into this:

enter image description here

I've looked at git-p4's --detect-branches option, but it doesn't look like it'll do what I want, either. If there were a way to get git p4 sync to set a parent for the "last" revision in the branch, rather than leaving it orphaned, that'd be perfect, but I'm not seeing a way.

All details of git-p4 aside, I think what I want is (in effect) a way to force a particular revision — specifically one of these orphaned (parentless) revisions at the "tail" of one of my branches — to have a parent link that's a SHA hash of my choosing, and then have that revision's hash (and all of its children's) recomputed to reflect it. I suppose I could put on a plumber's cap and write my own script to do this somehow, but I'm hoping there's a supported way.

Upvotes: 1

Views: 467

Answers (3)

VonC
VonC

Reputation: 1328312

git-p4 sync should be able to restore origin of branches correctly with Git 2.37 (Q3 2022):

See commit 944db25 (21 Mar 2022) by Kirill Frolov (kfrolov).
(Merged by Junio C Hamano -- gitster -- in commit 586f237, 20 May 2022)

git-p4: fix issue with multiple perforce remotes

Signed-off-by: Kirill Frolov

Single perforce branch might be sync'ed multiple times with different revision numbers, so it will be seen to Git as complete different commits.
This can be done by the following command:

git p4 sync --branch=NAME //perforce/path...

It is assumed, that this command applied multiple times and perforce repository changes between command invocations.

In such situation, git p4 will see multiple perforce branches with same name and different revision numbers.
The problem is that to make a shelve, git-p4 script will try to find "origin" branch, if not specified in command line explicitly.
And previously script selected any branch with same name and don't mention particular revision number.
Later this may cause failure of the command "git diff-tree -r $rev^ $rev""(man), so shelve can't be created (due to wrong origin branch/commit).

This commit fixes the heuristic by which git p4 selects origin branch:

  • first it tries to select branch with same perforce path and perforce revision,
  • and if it fails, then selects branch with only same perforce path (ignoring perforce revision number).

Upvotes: 0

Vitor
Vitor

Reputation: 1976

From your description it looks to me that you're missing the branchList configuration options. Please read the Branch Detection section of git-p4 documentation for more information.

By the way, the branching algorithm depends on the initial copy operation in P4 to have been done without file changes on order to find the exact commit in the source branch where the new branch started. Otherwise, the new branch will be created on the top of the source branch and you may end up with inconsistent code.

Upvotes: 0

Douglas Leeder
Douglas Leeder

Reputation: 53320

You can use filter-branch to do this.

  1. Clone branches separately
  2. Combine the repos using multiple remotes
  3. Use filter-branch to add parents to newer branches

From: https://labs.consol.de/development/git/2017/09/08/reunite-separate-git-repositories.html

It's probably better these days to use https://github.com/newren/git-filter-repo - but I haven't tried that.

https://github.com/newren/git-filter-repo/blob/main/Documentation/converting-from-filter-branch.md#re-grafting-history seems like it covers this case more cleanly.

Upvotes: 1

Related Questions