{"thread":{"id":"51675","subject":"git-p4: Clone p4 path with bidirectional integrations","startedAt":"2019-08-19T17:30:38Z","lastAt":"2019-08-23T03:13:35Z","messageCount":6,"participants":["Aaron Miller","Luke Diamand","Andrey"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"380718","messageId":"CALSvhyb7Td-ugzze9cSLXRjF78w=zE5=3yuMFZVeuXsCWLSjHg@mail.gmail.com","threadId":"51675","inReplyTo":null,"subject":"git-p4: Clone p4 path with bidirectional integrations","fromName":"Aaron Miller","fromEmail":"aaronkmiller@gmail.com","sentAt":"2019-08-19T17:29:59Z","receivedAt":"2019-08-19T17:30:38Z","isPatch":false,"sender":{"key":"aaronkmiller@gmail.com","avatar":null},"body":"Hi all,\n\nIs it possible to `git p4 clone --detect-branches` from a Perforce\npath which contains bidirectional integrations?\n\nI've tried a bunch of things to get this to work, but here's an\nexample which hopefully illustrates what I'm trying to accomplish\nand the issue I'm having.\n\nPerforce setup, assuming PWD is mapped to //depot/... in your client spec:\n\n  1. mkdir -p testing/master\n  2. touch testing/master/test1 && p4 add testing/master/test1 && p4 submit\n  3. p4 integrate //depot/testing/master/...\n//depot/testing/staging/... && p4 submit\n  3. touch testing/staging/test2 && p4 add testing/staging/test2 && p4 submit\n  4. p4 integrate //depot/testing/staging/...\n//depot/testing/master/... && p4 submit\n\nNow try to clone with git-p4:\n\n  1. git init p4_git_test && cd p4_git_test\n  2. git config git-p4.branchList master:staging\n  3. git config --add git-p4.branchList staging:master\n  4. git p4 clone //depot/testing/...@all --detect-branches .\n\nYou end up with a failure like:\n\n  Importing from //depot/testing/...@all into .\n  Reinitialized existing Git repository in /home/amiller/p4_git_test/.git/\n  Importing revision 1205832 (25%)\n      Importing new branch testing/master\n\n      Resuming with change 1205832\n  fatal: ambiguous argument 'refs/remotes/p4/testing/staging': unknown\nrevision or path not in the working tree.\n  Use '--' to separate paths from revisions, like this:\n  'git <command> [<revision>...] -- [<file>...]'\n  Command failed: ['git', 'rev-list', '--reverse', '--no-merges',\n'refs/remotes/p4/testing/staging']\n\nI'm using Git 2.22.1.\n\nThanks,\nAaron\n"},{"id":"380728","messageId":"CAE5ih78UOor3XT_hDofanoGUPLD1BC2y=pCbzF-Edm2mpRvjyQ@mail.gmail.com","threadId":"51675","inReplyTo":"CALSvhyb7Td-ugzze9cSLXRjF78w=zE5=3yuMFZVeuXsCWLSjHg@mail.gmail.com","subject":"Re: git-p4: Clone p4 path with bidirectional integrations","fromName":"Luke Diamand","fromEmail":"luke@diamand.org","sentAt":"2019-08-19T20:23:06Z","receivedAt":"2019-08-19T20:23:14Z","isPatch":false,"sender":{"key":"luke@diamand.org","avatar":"https://avatars.githubusercontent.com/u/5330967?v=4"},"body":"On Mon, 19 Aug 2019 at 18:30, Aaron Miller <aaronkmiller@gmail.com> wrote:\n>\n> Hi all,\n>\n> Is it possible to `git p4 clone --detect-branches` from a Perforce\n> path which contains bidirectional integrations?\n>\n> I've tried a bunch of things to get this to work, but here's an\n> example which hopefully illustrates what I'm trying to accomplish\n> and the issue I'm having.\n\nI have to admit I don't use the detect-branches code myself.\n\nIt's possible that running with \"-v\" might give a bit more information.\n\nCan you write a test case, or even just a shell script, that might\nhelp figure out what's going on.\n\nUnfortunately Perforce doesn't really know about branches, so git-p4\nhas to make a guess!\n\n>\n> Perforce setup, assuming PWD is mapped to //depot/... in your client spec:\n>\n>   1. mkdir -p testing/master\n>   2. touch testing/master/test1 && p4 add testing/master/test1 && p4 submit\n>   3. p4 integrate //depot/testing/master/...\n> //depot/testing/staging/... && p4 submit\n>   3. touch testing/staging/test2 && p4 add testing/staging/test2 && p4 submit\n>   4. p4 integrate //depot/testing/staging/...\n> //depot/testing/master/... && p4 submit\n>\n> Now try to clone with git-p4:\n>\n>   1. git init p4_git_test && cd p4_git_test\n>   2. git config git-p4.branchList master:staging\n>   3. git config --add git-p4.branchList staging:master\n>   4. git p4 clone //depot/testing/...@all --detect-branches .\n>\n> You end up with a failure like:\n>\n>   Importing from //depot/testing/...@all into .\n>   Reinitialized existing Git repository in /home/amiller/p4_git_test/.git/\n>   Importing revision 1205832 (25%)\n>       Importing new branch testing/master\n>\n>       Resuming with change 1205832\n>   fatal: ambiguous argument 'refs/remotes/p4/testing/staging': unknown\n> revision or path not in the working tree.\n>   Use '--' to separate paths from revisions, like this:\n>   'git <command> [<revision>...] -- [<file>...]'\n>   Command failed: ['git', 'rev-list', '--reverse', '--no-merges',\n> 'refs/remotes/p4/testing/staging']\n>\n> I'm using Git 2.22.1.\n>\n> Thanks,\n> Aaron\n"},{"id":"380754","messageId":"3442071566267276@iva5-049509bcc5d6.qloud-c.yandex.net","threadId":"51675","inReplyTo":"CALSvhyb7Td-ugzze9cSLXRjF78w=zE5=3yuMFZVeuXsCWLSjHg@mail.gmail.com","subject":"Re: git-p4: Clone p4 path with bidirectional integrations","fromName":"Andrey","fromEmail":"ahippo@yandex.ru","sentAt":"2019-08-20T02:14:36Z","receivedAt":"2019-08-20T02:14:44Z","isPatch":false,"sender":{"key":"ahippo@yandex.ru","avatar":null},"body":"\n19.08.2019, 13:30, \"Aaron Miller\" <aaronkmiller@gmail.com>:\n> Hi all,\n>\n> Is it possible to `git p4 clone --detect-branches` from a Perforce\n> path which contains bidirectional integrations?\n\nYes, but it would require some manual work most likely.\n\nFirst of all, git-p4 should normally take only one direction from bidirectional integrations on its own.\nDo you see \"p4 branch <branchABC> defines a mapping from <path1> to <path2>, but there exists another mapping from <path2> to <path1> already!\"?\nIf you do, it means that git-p4 will ignore <branchABC> mapping.\n\nAlso, just FYI, as far as I know, git-p4 doesn't create \"merge\" commits,\nso bidirectional integrations won't look different from ordinary commits in git commit graph.\n\n> I've tried a bunch of things to get this to work, but here's an\n> example which hopefully illustrates what I'm trying to accomplish\n> and the issue I'm having.\n>\n> Perforce setup, assuming PWD is mapped to //depot/... in your client spec:\n>\n>   1. mkdir -p testing/master\n>   2. touch testing/master/test1 && p4 add testing/master/test1 && p4 submit\n>   3. p4 integrate //depot/testing/master/...\n> //depot/testing/staging/... && p4 submit\n>   3. touch testing/staging/test2 && p4 add testing/staging/test2 && p4 submit\n>   4. p4 integrate //depot/testing/staging/...\n> //depot/testing/master/... && p4 submit\n>\n> Now try to clone with git-p4:\n>\n>   1. git init p4_git_test && cd p4_git_test\n>   2. git config git-p4.branchList master:staging\n>   3. git config --add git-p4.branchList staging:master\n>   4. git p4 clone //depot/testing/...@all --detect-branches .\n>\n> You end up with a failure like:\n>\n>   Importing from //depot/testing/...@all into .\n>   Reinitialized existing Git repository in /home/amiller/p4_git_test/.git/\n>   Importing revision 1205832 (25%)\n\nUh-oh, 5M commits!\nBut given that it fails at 25% instead of 1%,\nyou've got some luck. :)\n\n>       Importing new branch testing/master\n>\n>       Resuming with change 1205832\n>   fatal: ambiguous argument 'refs/remotes/p4/testing/staging': unknown\n> revision or path not in the working tree.\n>   Use '--' to separate paths from revisions, like this:\n>   'git <command> [<revision>...] -- [<file>...]'\n>   Command failed: ['git', 'rev-list', '--reverse', '--no-merges',\n> 'refs/remotes/p4/testing/staging']\n\nThis might not be just because of bidirectional integrations per se.\nThis error may happen if, say, there's a P4 branch mapping from staging to master,\nbut master was actually created before staging.\ngit-p4 tries to find a \"parent branch\" for master, but it doesn't exist yet,\nso git-p4 fails in an ugly way.\n\n\nOne way to filter out troublesome P4 branch mappings is to set git-p4.branchUser to a particular user.\nBut most likely, this won't help you because different people created different branch mappings over time.\n\nUnfortunately, there's _no_ git-p4.branchRegexp config option,\nbut it's fairly straightforward to implement -- patches welcome! ;)\n(getBranchMapping() needs to apply a regex to branch names before doing anything serious with them)\n\n\nThe other option is to manually set git-p4.branchList for all your branch pairs like\ngit config --add git-p4.branchList staging:master\ngit config --add git-p4.branchList master:branchA\ngit config --add git-p4.branchList master:branchB\n...\n(or by manually editing .git/config)\nNote, that you can't have master:staging together with staging:master,\notherwise you'll likely run into the same problem as before.\n\nThis might be simple or quite tedious depending on the history and branching strategies of your repositories.\nIt may be as easy as just dropping some p4 branch mappings.\nHowever, one of the repositories I had to deal with had almost random branching strategy (with most integrations done without predefined branch mappings),\nso I had to spend quite some time to trace the history and figure out which branches make the most sense in git.\n(Revision Graph in p4v was very helpful for figuring branching history out)\n\n\nAs I said, git-p4 doesn't create merge commits in git (or I can't see how to make them),\nso for repositories with simple/short history,\nI 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.\n(`git filter-branch` is only needed once in the very end after all `git replace` manipulations are done)\nIt's perhaps better to teach git-p4 to produce merge commits, but a bash script was a low-tech low-risk option for me.\n\nAlso, beware that git-p4 doesn't handle branch-into-non-empty directory properly.\nIf I remember correctly, something like\n`p4 copy //depot/branchA/... //depot/branchB/... ; p4 submit; p4 copy //depot/branchC/... //depot/branchB/...; p4 submit`\nwill result in branchB having _both_ branchA and branchC contents in git.\n`git filter-branch` or `git rebase` are your friends to workaround this.\n(or better fix git-p4, of course)\n\n> I'm using Git 2.22.1.\n>\n> Thanks,\n> Aaron\n\nHope this help,\nAndrey.\n\n"},{"id":"380869","messageId":"CALSvhyagGHY+JOaygd5++-GbNYskd3ys9ZQH3ha1pkeJaKQp1Q@mail.gmail.com","threadId":"51675","inReplyTo":"CAE5ih78UOor3XT_hDofanoGUPLD1BC2y=pCbzF-Edm2mpRvjyQ@mail.gmail.com","subject":"Re: git-p4: Clone p4 path with bidirectional integrations","fromName":"Aaron Miller","fromEmail":"aaronkmiller@gmail.com","sentAt":"2019-08-20T22:52:15Z","receivedAt":"2019-08-20T22:52:55Z","isPatch":false,"sender":{"key":"aaronkmiller@gmail.com","avatar":null},"body":"Hi Luke,\n\n> It's possible that running with \"-v\" might give a bit more information.\n\nHere's the output from that. I've set git-p4.branchUser in this test\nto avoid needlessly cluttering the output since I have a huge amount\nof branches in my Perforce repo, but otherwise I used the exact script\nwhich I've included later in this email:\n\nImporting from //depot/testing/...@all into .\nReinitialized existing Git repository in\n/home/amiller/Code/git-migration/repos/testing/.git/\nReading pipe: ['git', 'config', '--bool', 'git-p4.useclientspec']\nReading pipe: ['git', 'config', 'git-p4.branchUser']\nReading pipe: ['git', 'config', 'git-p4.user']\nReading pipe: ['git', 'config', 'git-p4.password']\nReading pipe: ['git', 'config', 'git-p4.port']\nReading pipe: ['git', 'config', 'git-p4.host']\nReading pipe: ['git', 'config', 'git-p4.client']\nReading pipe: ['git', 'config', '--int', 'git-p4.retries']\nReading pipe: ['git', 'config', '--int', 'git-p4.retries']\nOpening pipe: ['p4', '-r', '3', '-G', 'login', '-s']\nOpening pipe: p4 -r 3 -G branches -u amiller\nReading pipe: ['git', 'config', '--get-all', 'git-p4.branchList']\np4-git branches: []\ninitial parents: {}\nGetting p4 changes for //depot/testing/...\nOpening pipe: ['p4', '-r', '3', '-G', 'changes', '-m', '1']\nOpening pipe: ['p4', '-r', '3', '-G', 'changes',\n'//depot/testing/...@1,1048577']\nOpening pipe: ['p4', '-r', '3', '-G', 'changes',\n'//depot/testing/...@1048578,1206544']\nOpening pipe: ['p4', '-r', '3', '-G', 'describe', '-s', '1206099']\nImporting revision 1206099 (25%)Reading pipe: ['git', 'config',\n'--bool', 'core.ignorecase']\nbranch is master\n\n    Importing new branch testing/master\nOpening pipe: ['p4', '-r', '3', '-G', 'changes',\n'//depot/testing/master/...@1,1048577']\nOpening pipe: ['p4', '-r', '3', '-G', 'changes',\n'//depot/testing/master/...@1048578,1206098']\n\n    Resuming with change 1206099\nparent determined through known branches: staging\nlooking for initial parent for refs/remotes/p4/testing/master; current\nparent is refs/remotes/p4/testing/staging\nCreating temporary branch: refs/git-p4-tmp/1206099\ncommit into refs/git-p4-tmp/1206099\nReading pipe: ['git', 'config', '--bool', 'git-p4.keepEmptyCommits']\nOpening pipe: ['p4', '-r', '3', '-G', '-x', '-', 'print']\n//depot/testing/master/test1 --> test1 (0 MB)\ncheckpoint finished: progress checkpoint\n\nReading pipe: ['git', 'rev-list', '--reverse', '--no-merges',\n'refs/remotes/p4/testing/staging']\nfatal: ambiguous argument 'refs/remotes/p4/testing/staging': unknown\nrevision or path not in the working tree.\nUse '--' to separate paths from revisions, like this:\n'git <command> [<revision>...] -- [<file>...]'\nTraceback (most recent call last):\n  File \"/home/amiller/.bin/git-p4.py\", line 4173, in <module>\n    main()\n  File \"/home/amiller/.bin/git-p4.py\", line 4167, in main\n    if not cmd.run(args):\n  File \"/home/amiller/.bin/git-p4.py\", line 3923, in run\n    if not P4Sync.run(self, depotPaths):\n  File \"/home/amiller/.bin/git-p4.py\", line 3790, in run\n    self.importChanges(changes)\n  File \"/home/amiller/.bin/git-p4.py\", line 3451, in importChanges\n    blob = self.searchParent(parent, branch, tempBranch)\n  File \"/home/amiller/.bin/git-p4.py\", line 3374, in searchParent\n    \"--no-merges\", parent]):\n  File \"/home/amiller/.bin/git-p4.py\", line 237, in read_pipe_lines\n    die('Command failed: %s' % str(c))\n  File \"/home/amiller/.bin/git-p4.py\", line 165, in die\n    raise Exception(msg)\nException: Command failed: ['git', 'rev-list', '--reverse',\n'--no-merges', 'refs/remotes/p4/testing/staging']\n\n\n> Can you write a test case, or even just a shell script, that might\n> help figure out what's going on.\n\nNo problem:\n\n#!/bin/bash\n\n# perforce setup - assumes PWD is mapped to //depot/...\nmkdir -p testing/master\ntouch testing/master/test1\np4 add testing/master/test1\np4 submit -d 'test changelist 1'\n\np4 integrate //depot/testing/master/... //depot/testing/staging/...\np4 submit -d 'test changelist 2'\n\ntouch testing/staging/test2\np4 add testing/staging/test2\np4 submit -d 'test changelist 3'\n\np4 integrate //depot/testing/staging/... //depot/testing/master/...\np4 submit -d 'test changelist 4'\n\n# clone with git-p4:\ngit init p4_git_test\ncd p4_git_test\ngit config git-p4.branchList master:staging\ngit config --add git-p4.branchList staging:master\ngit p4 clone //depot/testing/...@all --detect-branches --verbose .\n\n\nThanks,\nAaron\n"},{"id":"380871","messageId":"CALSvhyZUphJ4+Vb5MD-KS9OV7DOK6ahwvfBdg0JiNWbT7GxzWA@mail.gmail.com","threadId":"51675","inReplyTo":"3442071566267276@iva5-049509bcc5d6.qloud-c.yandex.net","subject":"Re: git-p4: Clone p4 path with bidirectional integrations","fromName":"Aaron Miller","fromEmail":"aaronkmiller@gmail.com","sentAt":"2019-08-20T23:45:44Z","receivedAt":"2019-08-20T23:46:24Z","isPatch":false,"sender":{"key":"aaronkmiller@gmail.com","avatar":null},"body":"Hi Andrey,\n\nThanks so much for this detailed response, I really appreciate it.\n\n> First of all, git-p4 should normally take only one direction from bidirectional integrations on its own.\n> Do you see \"p4 branch <branchABC> defines a mapping from <path1> to <path2>, but there exists another mapping from <path2> to <path1> already!\"?\n> If you do, it means that git-p4 will ignore <branchABC> mapping.\n\nI was afraid that was the case!\n\n> Also, just FYI, as far as I know, git-p4 doesn't create \"merge\" commits,\n> so bidirectional integrations won't look different from ordinary commits in git commit graph.\n\nAh, I didn't realize that, thank you. Perhaps I should just sync each\nbranch separately then, ignoring branch mappings entirely and be done\nwith it.\n\nI was hoping to generate a commit graph that properly represents\nintegrations as merge commits because our Perforce branches are quite\nlarge. Storing diffs of integrations rather than discrete commits\nwould result in a much smaller Git repository for us. There are\n*quite* a lot of integration commits.\n\nI wonder how hard it would be to modify git-p4 to use merge commits? I\nwill take a look at the source. I'm somewhat surprised that's not the\ncase to begin with though? Maybe someone else can chime in on why\nmerge commits aren't used.\n\n> Uh-oh, 5M commits!\n> But given that it fails at 25% instead of 1%,\n> you've got some luck. :)\n\nHehe :) Fortunately I don't have to migrate *all* of those commits,\nbut still a fair number.\n\n> This might not be just because of bidirectional integrations per se.\n\nI should have mentioned - there were no P4 branch mappings defined for\nthe depot paths in the test case I shared (maybe that's obvious).\n\n> This error may happen if, say, there's a P4 branch mapping from staging to master,\n> but master was actually created before staging.\n> git-p4 tries to find a \"parent branch\" for master, but it doesn't exist yet,\n> so git-p4 fails in an ugly way.\n\nYeah this is exactly correct, I've tested precisely this scenario.\nActually that's what two of the real branches I am trying to migrate\nlook like.\n\n> One way to filter out troublesome P4 branch mappings is to set git-p4.branchUser to a particular user.\n> But most likely, this won't help you because different people created different branch mappings over time.\n\nI was thinking I could set git-p4.branchUser to a user that hasn't\ncreated any branches at all and then define branch mappings I care\nabout in git-p4.branchList.\n\nBut pretty much all of our branches either have bidirectional\nintegrations or a situation like you described above where branchA was\ncreated before branchB, and branchB integrates into branchA.\n\n> Unfortunately, there's _no_ git-p4.branchRegexp config option,\n> but it's fairly straightforward to implement -- patches welcome! ;)\n> (getBranchMapping() needs to apply a regex to branch names before doing anything serious with them)\n\nThat would be a neat option! It's not really filtering the branch\nmappings which is my issue though. The number of branches is small\nenough that I can manage the mappings manually.\n\n> Note, that you can't have master:staging together with staging:master,\n> otherwise you'll likely run into the same problem as before.\n\nYeah this is really the crux of my issue.\n\n> This might be simple or quite tedious depending on the history and branching strategies of your repositories.\n> It may be as easy as just dropping some p4 branch mappings.\n\nI'm thinking if I'm not getting merge commits anyway I may as well\njust forget about the branch mappings entirely.\n\n> 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.\n\nFortunately our branching strategy was *mostly* well-defined and we do\nhave Perforce mappings defined between our branches. However most\nintegrations didn't actually use the branch mappings, just manually\nspecified depot paths. But they did fall under the branch mapping\nscopes.\n\n> so for repositories with simple/short history,\n\nUnfortunately our repo history is anything but short or simple :(\n\n> 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.\n>\n> (`git filter-branch` is only needed once in the very end after all `git replace` manipulations are done)\n> 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.\n>\n> Also, beware that git-p4 doesn't handle branch-into-non-empty directory properly.\n> If I remember correctly, something like\n> `p4 copy //depot/branchA/... //depot/branchB/... ; p4 submit; p4 copy //depot/branchC/... //depot/branchB/...; p4 submit`\n> will result in branchB having _both_ branchA and branchC contents in git.\n> `git filter-branch` or `git rebase` are your friends to workaround this.\n> (or better fix git-p4, of course)\n\nThese are great tips, thanks! Maybe what I will do is sync each branch\nseparately with no branch mappings, then use this technique to create\nmerge commits for the initial branch creation commits only and not\nworry about any other integrations.\n\n-Aaron\n"},{"id":"380994","messageId":"2393271566529584@vla1-74bb1214b343.qloud-c.yandex.net","threadId":"51675","inReplyTo":"CALSvhyZUphJ4+Vb5MD-KS9OV7DOK6ahwvfBdg0JiNWbT7GxzWA@mail.gmail.com","subject":"Re: git-p4: Clone p4 path with bidirectional integrations","fromName":"Andrey","fromEmail":"ahippo@yandex.ru","sentAt":"2019-08-23T03:06:24Z","receivedAt":"2019-08-23T03:13:35Z","isPatch":false,"sender":{"key":"ahippo@yandex.ru","avatar":null},"body":"Aaron,\n\n20.08.2019, 19:46, \"Aaron Miller\" <aaronkmiller@gmail.com>:\n>>  Also, just FYI, as far as I know, git-p4 doesn't create \"merge\" commits,\n>>  so bidirectional integrations won't look different from ordinary commits in git commit graph.\n>\n> Ah, I didn't realize that, thank you. Perhaps I should just sync each\n> branch separately then, ignoring branch mappings entirely and be done\n> with it.\n\nYou could do it this way too.\nBut this way your branches will be completely independent.\nHowever, with --detect-branches, you'll preserve the information on which branch was branched off at which point.\n(it's useful for release branches or feature branches; but not really for main and testing branching model)\n\n> I was hoping to generate a commit graph that properly represents\n> integrations as merge commits because our Perforce branches are quite\n> large. Storing diffs of integrations rather than discrete commits\n> would result in a much smaller Git repository for us. There are\n> *quite* a lot of integration commits.\nNot sure if there'll be a big difference in terms of Git repository size.\nGit is quite efficient with its delta compression and pack files.\n\n> I wonder how hard it would be to modify git-p4 to use merge commits? I\n> will take a look at the source.\nIt's somewhere around importChanges() and commit(), I suppose.\nIt seems simple on git side (just specify additional parents when creating a commit using \"merge\" keyword for git fast-import),\nbut may be more complicated on Perforce side (to find the parent(s)).\n\n> I'm somewhat surprised that's not the\n> case to begin with though? Maybe someone else can chime in on why\n> merge commits aren't used.\nYeah, it comes as a bad surprise.\nOne reason I can think of is bi-directional interaction between Perforce and Git -- perhaps some information is lost during submit to P4 and then reimport back to Git.\nIt might also get tricky during import of changelists that span several branches (shouldn't probably be considered a merge though).\n\n>>  This might not be just because of bidirectional integrations per se.\n>\n> I should have mentioned - there were no P4 branch mappings defined for\n> the depot paths in the test case I shared (maybe that's obvious).\nWell, you had git-p4.branchList defined, which is enough for --detect-branches logic to kick in.\n\n>>  One way to filter out troublesome P4 branch mappings is to set git-p4.branchUser to a particular user.\n>>  But most likely, this won't help you because different people created different branch mappings over time.\n>\n> I was thinking I could set git-p4.branchUser to a user that hasn't\n> created any branches at all and then define branch mappings I care\n> about in git-p4.branchList.\nYeah, it's a good idea. (I did the same)\nAs far as I remember, you can even use a non-existing user for git-p4.branchUser.\n\n>>  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.\n>>\n>>  (`git filter-branch` is only needed once in the very end after all `git replace` manipulations are done)\n>>  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.\n>>\n>>  Also, beware that git-p4 doesn't handle branch-into-non-empty directory properly.\n>>  If I remember correctly, something like\n>>  `p4 copy //depot/branchA/... //depot/branchB/... ; p4 submit; p4 copy //depot/branchC/... //depot/branchB/...; p4 submit`\n>>  will result in branchB having _both_ branchA and branchC contents in git.\n>>  `git filter-branch` or `git rebase` are your friends to workaround this.\n>>  (or better fix git-p4, of course)\nAnother suggestion: after import into git is done, it might be useful to cross-check tips of git branches against tips of corresponding Perforce branches.\n(some files may exist in git when they are deleted from Perforce due to the aforementioned branch-into-non-empty directory issue)\n\n> These are great tips, thanks! Maybe what I will do is sync each branch\n> separately with no branch mappings, then use this technique to create\n> merge commits for the initial branch creation commits only and not\n> worry about any other integrations.\nIf commits for integrations have consistent commit messages,\nyou might be able to get merge commits using `git replace` cheaper than by modifying git-p4 itself (which can't rely on commit messages).\n\n\n-- \nAndrey.\n\n"}]}