19.08.2019, 13:30, "Aaron Miller" <aaronkmil...@gmail.com>:
> Hi all,
>
> Is it possible to `git p4 clone --detect-branches` from a Perforce
> path which contains bidirectional integrations?

Yes, but it would require some manual work most likely.

First of all, git-p4 should normally take only one direction from bidirectional 
integrations on its own.
Do you see "p4 branch <branchABC> defines a mapping from <path1> to <path2>, 
but there exists another mapping from <path2> to <path1> already!"?
If you do, it means that git-p4 will ignore <branchABC> mapping.

Also, just FYI, as far as I know, git-p4 doesn't create "merge" commits,
so bidirectional integrations won't look different from ordinary commits in git 
commit graph.

> I've tried a bunch of things to get this to work, but here's an
> example which hopefully illustrates what I'm trying to accomplish
> and the issue I'm having.
>
> Perforce setup, assuming PWD is mapped to //depot/... in your client spec:
>
>   1. mkdir -p testing/master
>   2. touch testing/master/test1 && p4 add testing/master/test1 && p4 submit
>   3. p4 integrate //depot/testing/master/...
> //depot/testing/staging/... && p4 submit
>   3. touch testing/staging/test2 && p4 add testing/staging/test2 && p4 submit
>   4. p4 integrate //depot/testing/staging/...
> //depot/testing/master/... && p4 submit
>
> Now try to clone with git-p4:
>
>   1. git init p4_git_test && cd p4_git_test
>   2. git config git-p4.branchList master:staging
>   3. git config --add git-p4.branchList staging:master
>   4. git p4 clone //depot/testing/...@all --detect-branches .
>
> You end up with a failure like:
>
>   Importing from //depot/testing/...@all into .
>   Reinitialized existing Git repository in /home/amiller/p4_git_test/.git/
>   Importing revision 1205832 (25%)

Uh-oh, 5M commits!
But given that it fails at 25% instead of 1%,
you've got some luck. :)

>       Importing new branch testing/master
>
>       Resuming with change 1205832
>   fatal: ambiguous argument 'refs/remotes/p4/testing/staging': unknown
> revision or path not in the working tree.
>   Use '--' to separate paths from revisions, like this:
>   'git <command> [<revision>...] -- [<file>...]'
>   Command failed: ['git', 'rev-list', '--reverse', '--no-merges',
> 'refs/remotes/p4/testing/staging']

This might not be just because of bidirectional integrations per se.
This error may happen if, say, there's a P4 branch mapping from staging to 
master,
but master was actually created before staging.
git-p4 tries to find a "parent branch" for master, but it doesn't exist yet,
so git-p4 fails in an ugly way.


One way to filter out troublesome P4 branch mappings is to set 
git-p4.branchUser to a particular user.
But most likely, this won't help you because different people created different 
branch mappings over time.

Unfortunately, there's _no_ git-p4.branchRegexp config option,
but it's fairly straightforward to implement -- patches welcome! ;)
(getBranchMapping() needs to apply a regex to branch names before doing 
anything serious with them)


The other option is to manually set git-p4.branchList for all your branch pairs 
like
git config --add git-p4.branchList staging:master
git config --add git-p4.branchList master:branchA
git config --add git-p4.branchList master:branchB
...
(or by manually editing .git/config)
Note, that you can't have master:staging together with staging:master,
otherwise you'll likely run into the same problem as before.

This might be simple or quite tedious depending on the history and branching 
strategies of your repositories.
It may be as easy as just dropping some p4 branch mappings.
However, one of the repositories I had to deal with had almost random branching 
strategy (with most integrations done without predefined branch mappings),
so I had to spend quite some time to trace the history and figure out which 
branches make the most sense in git.
(Revision Graph in p4v was very helpful for figuring branching history out)


As I said, git-p4 doesn't create merge commits in git (or I can't see how to 
make them),
so for repositories with simple/short history,
I recreated those merge commits manually (well, in a bash script) using `git 
replace --graft <commit> <parent1> <parent2>` followed by `git filter-branch 
--tag-name-filter cat -- --all` to make grafts permanent.
(`git filter-branch` is only needed once in the very end after all `git 
replace` manipulations are done)
It's perhaps better to teach git-p4 to produce merge commits, but a bash script 
was a low-tech low-risk option for me.

Also, beware that git-p4 doesn't handle branch-into-non-empty directory 
properly.
If I remember correctly, something like
`p4 copy //depot/branchA/... //depot/branchB/... ; p4 submit; p4 copy 
//depot/branchC/... //depot/branchB/...; p4 submit`
will result in branchB having _both_ branchA and branchC contents in git.
`git filter-branch` or `git rebase` are your friends to workaround this.
(or better fix git-p4, of course)

> I'm using Git 2.22.1.
>
> Thanks,
> Aaron

Hope this help,
Andrey.

Reply via email to