{"thread":{"id":"46207","subject":"Restoring detached HEADs after Git operations","startedAt":"2017-06-19T08:46:52Z","lastAt":"2017-06-19T20:14:05Z","messageCount":14,"participants":["Patrick Lehmann","Lars Schneider","Stefan Beller","Jeff King","Junio C Hamano","Ævar Arnfjörð Bjarmason"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"322550","messageId":"0092CDD27C5F9D418B0F3E9B5D05BE08010287DF@SBS2011.opfingen.plc2.de","threadId":"46207","inReplyTo":null,"subject":"Restoring detached HEADs after Git operations","fromName":"Patrick Lehmann","fromEmail":"patrick.lehmann@plc2.de","sentAt":"2017-06-19T08:46:45Z","receivedAt":"2017-06-19T08:46:52Z","isPatch":false,"sender":{"key":"patrick.lehmann@plc2.de","avatar":"https://gravatar.com/avatar/861fc81252f222aa3db2b3f869cde9d2a4759bd96bc31b40d01a1609a9e7d559?d=mp&s=160"},"body":"Hello,\n\nI wrote a Bash script to recover branch names after Git operations have create detached HEADs in a Git repository containing lots of Git submodules. The script works recursively.\n\nI would like to see:\na) that script or algorithm being integrated into Git by default\nb) that as a default behavior for all Git operations creating detached HEADs\n\nThat's the command:\n--------------------------------\ngit submodule foreach --recursive  'HEAD=$(git branch --list | head -n 1); if [[ \"$HEAD\" == *HEAD* ]]; then REF=$(git rev-parse HEAD); FOUND=0; for Branch in $(git branch --list | grep \"^  \" | sed -e \"s/  //\" ); do if [[ \"$(git rev-parse \"$Branch\")\" == $REF ]]; then echo -e \"  \\e[36mCheckout $Branch...\\e[0m\"; git checkout $Branch; FOUND=1; break; fi done; if [[ $FOUND -eq 0 ]]; then echo -e \"  \\e[31mNo matching branch found.\\e[0m\"; fi else echo -e \"  \\e[36mNothing to do.\\e[0m\"; fi'\n--------------------------------\n\nHow does it work:\n1. It uses git submodule foreach to dive into each Git submodule and execute a series of Bash commands.\n2. It's reading the list of branches and checks if the submodule is in detached mode. The first line contains the string HEAD.\n3. Retrieve the hash of the detached HEAD\n4. Iterate all local branches and get their hashes\n5. Compare the branch hashes with the detached HEAD's hash. If it matches do a checkout.\n6. Report if no branch name was found or if a HEAD was not in detached mode.\n\nThe Bash code with line breaks and indentation:\n--------------------------------\nHEAD=$(git branch --list | head -n 1)\nif [[ \"$HEAD\" == *HEAD* ]]; then\n  REF=$(git rev-parse HEAD)\n  FOUND=0\n  for Branch in $(git branch --list | grep \"^  \" | sed -e \"s/  //\" ); do\n    if [[ \"$(git rev-parse \"$Branch\")\" == $REF ]]; then\n      echo -e \"  \\e[36mCheckout $Branch...\\e[0m\"\n      git checkout $Branch\n      FOUND=1\n      break\n    fi\n  done\n  if [[ $FOUND -eq 0 ]]; then\n    echo -e \"  \\e[31mNo matching branch found.\\e[0m\"\n  fi\nelse\n  echo -e \"  \\e[36mNothing to do.\\e[0m\"\nfi\n--------------------------------\n\nAre their any chances to get it integrated into Git?\n\nI tried to register that code as a Git alias, but git config complains about quote problem not showing where. It neither specifies if it's a single or double quote problem. Any advice on how to register that piece of code as an alias?\n\nIf wished, I think I could expand the script to also recover hash values to Git tags if no branch was found.\n\nKind regards\n    Patrick Lehmann\n"},{"id":"322554","messageId":"88AC6179-75D6-416B-9235-C628D6C59CA5@gmail.com","threadId":"46207","inReplyTo":"0092CDD27C5F9D418B0F3E9B5D05BE08010287DF@SBS2011.opfingen.plc2.de","subject":"Re: Restoring detached HEADs after Git operations","fromName":"Lars Schneider","fromEmail":"larsxschneider@gmail.com","sentAt":"2017-06-19T09:30:21Z","receivedAt":"2017-06-19T09:30:30Z","isPatch":false,"sender":{"key":"larsxschneider@gmail.com","avatar":"https://avatars.githubusercontent.com/u/477434?v=4"},"body":"\n> On 19 Jun 2017, at 10:46, Patrick Lehmann <Patrick.Lehmann@plc2.de> wrote:\n> \n> Hello,\n> \n> I wrote a Bash script to recover branch names after Git operations have create detached HEADs in a Git repository containing lots of Git submodules. The script works recursively.\n\nI did run into this situation myself and therefore\nI understand your motivation. I've CC'ed Stefan as\nhe is a Submodule expert!\n\n\n> I would like to see:\n> a) that script or algorithm being integrated into Git by default\n> b) that as a default behavior for all Git operations creating detached HEADs\n> \n> That's the command:\n> --------------------------------\n> git submodule foreach --recursive  'HEAD=$(git branch --list | head -n 1); if [[ \"$HEAD\" == *HEAD* ]]; then REF=$(git rev-parse HEAD); FOUND=0; for Branch in $(git branch --list | grep \"^  \" | sed -e \"s/  //\" ); do if [[ \"$(git rev-parse \"$Branch\")\" == $REF ]]; then echo -e \"  \\e[36mCheckout $Branch...\\e[0m\"; git checkout $Branch; FOUND=1; break; fi done; if [[ $FOUND -eq 0 ]]; then echo -e \"  \\e[31mNo matching branch found.\\e[0m\"; fi else echo -e \"  \\e[36mNothing to do.\\e[0m\"; fi'\n> --------------------------------\n> \n> How does it work:\n> 1. It uses git submodule foreach to dive into each Git submodule and execute a series of Bash commands.\n> 2. It's reading the list of branches and checks if the submodule is in detached mode. The first line contains the string HEAD.\n> 3. Retrieve the hash of the detached HEAD\n> 4. Iterate all local branches and get their hashes\n> 5. Compare the branch hashes with the detached HEAD's hash. If it matches do a checkout.\n\nIf there are multiple branches with the same hash then\nyour script would pick the first one. Can you imagine a\nsituation where this would be a problem?\n\nPlus, you are looking only at local branches. Wouldn't it\nmake sense to look at remote branches, too?\n\n\n> 6. Report if no branch name was found or if a HEAD was not in detached mode.\n> \n> The Bash code with line breaks and indentation:\n> --------------------------------\n> HEAD=$(git branch --list | head -n 1)\n> if [[ \"$HEAD\" == *HEAD* ]]; then\n>  REF=$(git rev-parse HEAD)\n>  FOUND=0\n>  for Branch in $(git branch --list | grep \"^  \" | sed -e \"s/  //\" ); do\n\nThere is a convenient \"git for-each-ref\" function to iterate over\nbranches in scripts. See here an example:\nhttps://github.com/larsxschneider/scotty/blob/master/admin/oss-fork.sh#L88\n\n\n>    if [[ \"$(git rev-parse \"$Branch\")\" == $REF ]]; then\n>      echo -e \"  \\e[36mCheckout $Branch...\\e[0m\"\n>      git checkout $Branch\n>      FOUND=1\n>      break\n>    fi\n>  done\n>  if [[ $FOUND -eq 0 ]]; then\n>    echo -e \"  \\e[31mNo matching branch found.\\e[0m\"\n>  fi\n> else\n>  echo -e \"  \\e[36mNothing to do.\\e[0m\"\n> fi\n> --------------------------------\n> \n> Are their any chances to get it integrated into Git?\n> \n> I tried to register that code as a Git alias, but git config complains about quote problem not showing where. It neither specifies if it's a single or double quote problem. Any advice on how to register that piece of code as an alias?\n\nTry to escape \". See here for an example:\nhttps://github.com/Autodesk/enterprise-config-for-git/blob/master/config.include#L76-L94\n\n\n> If wished, I think I could expand the script to also recover hash values to Git tags if no branch was found.\n\nIt would be indeed nice to see the tagged version on my prompt.\n\n--\n\nSubmodule processing is already quite slow if you have many of them.\nI wonder how much this approach would affect the performance.\n\n- Lars\n\n"},{"id":"322557","messageId":"0092CDD27C5F9D418B0F3E9B5D05BE080102887B@SBS2011.opfingen.plc2.de","threadId":"46207","inReplyTo":"88AC6179-75D6-416B-9235-C628D6C59CA5@gmail.com","subject":"AW: Restoring detached HEADs after Git operations","fromName":"Patrick Lehmann","fromEmail":"patrick.lehmann@plc2.de","sentAt":"2017-06-19T09:52:28Z","receivedAt":"2017-06-19T09:52:41Z","isPatch":false,"sender":{"key":"patrick.lehmann@plc2.de","avatar":"https://gravatar.com/avatar/861fc81252f222aa3db2b3f869cde9d2a4759bd96bc31b40d01a1609a9e7d559?d=mp&s=160"},"body":"Hello Lars,\n\nfor your questions:\n> If there are multiple branches with the same hash then your script would pick the first one. Can you imagine a situation where this would be a problem?\n\nI can't think of a good solution to resolve it automatically. Maybe a script could print that there are multiple possibilities and it choose the first branch in the list.\n\n\n> Plus, you are looking only at local branches. Wouldn't it make sense to look at remote branches, too?\n\nThis is also related to restoring tags. If we go this way, we should have this priority list:\n- local branches\n- remote branches\n- tags\n\n\n> Submodule processing is already quite slow if you have many of them. I wonder how much this approach would affect the performance.\n\nYes. It takes a few seconds to iterate all the submodules. It could be improved if the processing wouldn't be based on slow Bash scripts spawning lot's of sub-shells to execute multiple Git commands.\n\n\n\nIs there a way to avoid detached DEADs at the beginning?\nMany submodules are attached to a reference and get detached to a hash of the same reference. It would be better, if they never get detached when the current and new hash are the same.\n\n\nKind regards\n    Patrick\n\n________________________________________\nVon: git-owner@vger.kernel.org [git-owner@vger.kernel.org]&quot; im Auftrag von &quot;Lars Schneider [larsxschneider@gmail.com]\nGesendet: Montag, 19. Juni 2017 11:30\nBis: Patrick Lehmann\nCc: Git Mailinglist; Stefan Beller\nBetreff: Re: Restoring detached HEADs after Git operations\n\n> On 19 Jun 2017, at 10:46, Patrick Lehmann <Patrick.Lehmann@plc2.de> wrote:\n>\n> Hello,\n>\n> I wrote a Bash script to recover branch names after Git operations have create detached HEADs in a Git repository containing lots of Git submodules. The script works recursively.\n\nI did run into this situation myself and therefore\nI understand your motivation. I've CC'ed Stefan as\nhe is a Submodule expert!\n\n\n> I would like to see:\n> a) that script or algorithm being integrated into Git by default\n> b) that as a default behavior for all Git operations creating detached HEADs\n>\n> That's the command:\n> --------------------------------\n> git submodule foreach --recursive  'HEAD=$(git branch --list | head -n 1); if [[ \"$HEAD\" == *HEAD* ]]; then REF=$(git rev-parse HEAD); FOUND=0; for Branch in $(git branch --list | grep \"^  \" | sed -e \"s/  //\" ); do if [[ \"$(git rev-parse \"$Branch\")\" == $REF ]]; then echo -e \"  \\e[36mCheckout $Branch...\\e[0m\"; git checkout $Branch; FOUND=1; break; fi done; if [[ $FOUND -eq 0 ]]; then echo -e \"  \\e[31mNo matching branch found.\\e[0m\"; fi else echo -e \"  \\e[36mNothing to do.\\e[0m\"; fi'\n> --------------------------------\n>\n> How does it work:\n> 1. It uses git submodule foreach to dive into each Git submodule and execute a series of Bash commands.\n> 2. It's reading the list of branches and checks if the submodule is in detached mode. The first line contains the string HEAD.\n> 3. Retrieve the hash of the detached HEAD\n> 4. Iterate all local branches and get their hashes\n> 5. Compare the branch hashes with the detached HEAD's hash. If it matches do a checkout.\n\nIf there are multiple branches with the same hash then\nyour script would pick the first one. Can you imagine a\nsituation where this would be a problem?\n\nPlus, you are looking only at local branches. Wouldn't it\nmake sense to look at remote branches, too?\n\n\n> 6. Report if no branch name was found or if a HEAD was not in detached mode.\n>\n> The Bash code with line breaks and indentation:\n> --------------------------------\n> HEAD=$(git branch --list | head -n 1)\n> if [[ \"$HEAD\" == *HEAD* ]]; then\n>  REF=$(git rev-parse HEAD)\n>  FOUND=0\n>  for Branch in $(git branch --list | grep \"^  \" | sed -e \"s/  //\" ); do\n\nThere is a convenient \"git for-each-ref\" function to iterate over\nbranches in scripts. See here an example:\nhttps://github.com/larsxschneider/scotty/blob/master/admin/oss-fork.sh#L88\n\n\n>    if [[ \"$(git rev-parse \"$Branch\")\" == $REF ]]; then\n>      echo -e \"  \\e[36mCheckout $Branch...\\e[0m\"\n>      git checkout $Branch\n>      FOUND=1\n>      break\n>    fi\n>  done\n>  if [[ $FOUND -eq 0 ]]; then\n>    echo -e \"  \\e[31mNo matching branch found.\\e[0m\"\n>  fi\n> else\n>  echo -e \"  \\e[36mNothing to do.\\e[0m\"\n> fi\n> --------------------------------\n>\n> Are their any chances to get it integrated into Git?\n>\n> I tried to register that code as a Git alias, but git config complains about quote problem not showing where. It neither specifies if it's a single or double quote problem. Any advice on how to register that piece of code as an alias?\n\nTry to escape \". See here for an example:\nhttps://github.com/Autodesk/enterprise-config-for-git/blob/master/config.include#L76-L94\n\n\n> If wished, I think I could expand the script to also recover hash values to Git tags if no branch was found.\n\nIt would be indeed nice to see the tagged version on my prompt.\n\n--\n\nSubmodule processing is already quite slow if you have many of them.\nI wonder how much this approach would affect the performance.\n\n- Lars\n"},{"id":"322573","messageId":"CAGZ79kY9JhWYuPMjHac=gD+dPcma1hVTtbPKdgbTqYx0oMECRg@mail.gmail.com","threadId":"46207","inReplyTo":"0092CDD27C5F9D418B0F3E9B5D05BE08010287DF@SBS2011.opfingen.plc2.de","subject":"Re: Restoring detached HEADs after Git operations","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-06-19T16:31:44Z","receivedAt":"2017-06-19T16:31:50Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Mon, Jun 19, 2017 at 1:46 AM, Patrick Lehmann\n<Patrick.Lehmann@plc2.de> wrote:\n> Hello,\n>\n> I wrote a Bash script to recover branch names after Git operations have create detached HEADs in a Git repository containing lots of Git submodules. The script works recursively.\n\nCool. :)\n\nYou may also like\nhttps://public-inbox.org/git/20170501180058.8063-5-sbeller@google.com/\nhttps://public-inbox.org/git/20170501180058.8063-6-sbeller@google.com/\n\nThese patches are still on my plate, they are not landed yet as I had issues\ncoming up with a good convincing commit message.\n\nThey are essentially putting submodules back on a branch (if configured).\nLet's see how this differs from your solution.\n\n\n> I would like to see:\n> a) that script or algorithm being integrated into Git by default\n\nFor that you'd want to send a patch, see Documentation/SubmittingPatches.\nWe'd want to discuss if this command is an independent command\n(\"git submodule reattachHEADs\", name subject to bikeshedding ;) )\nor if it is a configurable option that is obeyed by anything that touches\nsubmodules (which I would prefer, as this mode seems to be the\n\"correct default\". When having it as a mode we can switch the default\neventually such that submodules are always on a branch).\n\n> b) that as a default behavior for all Git operations creating detached HEADs\n\nchanging defaults is hard. Let's go with a) first and then people will\nreport how\nawesome the new mode/command is and then it is easier to see how this\nmay be a good default. :)\n\n>\n> That's the command:\n> --------------------------------\n(reformatted for readability:)\n\ngit submodule foreach --recursive\n  'HEAD=$(git branch --list | head -n 1);\n    if [[ \"$HEAD\" == *HEAD* ]]; then\n      REF=$(git rev-parse HEAD);\n      FOUND=0;\n      for Branch in $(git branch --list | grep \"^  \" | sed -e \"s/  //\" );\n      do\n        if [[ \"$(git rev-parse \"$Branch\")\" == $REF ]]; then\n          echo -e \"  \\e[36mCheckout $Branch...\\e[0m\";\n          git checkout $Branch;\n          FOUND=1;\n          break;\n        fi\n      done;\n      if [[ $FOUND -eq 0 ]]; then\n        echo -e \"  \\e[31mNo matching branch found.\\e[0m\";\n      fi\n    else\n      echo -e \"  \\e[36mNothing to do.\\e[0m\";\n    fi'\n\n> --------------------------------\n>\n> How does it work:\n> 1. It uses git submodule foreach to dive into each Git submodule and execute a series of Bash commands.\n\nIf you want to see it upstream eventually, we'd make it shell commands.\nThere are some subtle differences between shell and bash,\none of them is the way conditions are written. I think plain shell\ndoes not support [[ ]], so that would become\n\n  if test $FOUND -eq 0\n  then\n    echo ...\n\nMaybe look at git-submodule.sh for coding style suggestions.\n\n> 2. It's reading the list of branches and checks if the submodule is in detached mode. The first line contains the string HEAD.\n\nThis works for you but some crazy person may have a branch containing\nHEAD in their branch name. ;)\n(\"git checkout -b notADetachedHEAD\")\n\nI think that check can be improved via\n\n    if test $(git symbolic-ref HEAD 2>/dev/null >/dev/null) -eq 128\n    then\n      # detached HEAD\n    else\n      # on a branch\n    fi\n\nso if the output of symbolic-ref starts with ref then it is on a\nbranch. In detached HEAD\n\n> 3. Retrieve the hash of the detached HEAD\n> 4. Iterate all local branches and get their hashes\n\n  What happens (/should happen) when multiple branches have the same sha1?\n  With this implementation the first wins? Is this 'lazy guessing' desired?\n  The patches referenced above assumed you'd have submodule.NAME.branch\n  set and we'd reattach to that branch only (if matching hashes)\n\n> 5. Compare the branch hashes with the detached HEAD's hash. If it matches do a checkout.\n\nSpeaking of checkout: checkout --recurse-submodules is a\nthing in the latest version of Git, but it also detaches HEADs.\n\nI'd like to have reattaching HEADs in there and then combined with\n\"git config submodule.recurse true\", which is in master but no release\na plain \"git checkout <branch>\" in the superproject would put the submodules\non branches.\n\nUsing checkout within git submodule-foreach works of course just as fine.\nNote: Currently Prathamesh Chavan converts git-submodule-foreach to C\nhttps://public-inbox.org/git/CAME+mvUrzVxpRdPDvA1ZyatNm2R27QGJVjSB3=KX85CEedMaRQ@mail.gmail.com/\nso it will be faster. In the process of doing so, we surfaced a couple\nof bugs, but\nthey would not impact this script AFAICT.\n\n\n> 6. Report if no branch name was found or if a HEAD was not in detached mode.\n\n... and it is colored unconditionally in red. Maybe have a look at\n    git config --get-color[bool]\nwhich can help in figuring out if we want to print color codes.\n\n> The Bash code with line breaks and indentation:\n> --------------------------------\n> HEAD=$(git branch --list | head -n 1)\n> if [[ \"$HEAD\" == *HEAD* ]]; then\n>   REF=$(git rev-parse HEAD)\n>   FOUND=0\n>   for Branch in $(git branch --list | grep \"^  \" | sed -e \"s/  //\" ); do\n>     if [[ \"$(git rev-parse \"$Branch\")\" == $REF ]]; then\n>       echo -e \"  \\e[36mCheckout $Branch...\\e[0m\"\n>       git checkout $Branch\n>       FOUND=1\n>       break\n>     fi\n>   done\n>   if [[ $FOUND -eq 0 ]]; then\n>     echo -e \"  \\e[31mNo matching branch found.\\e[0m\"\n>   fi\n> else\n>   echo -e \"  \\e[36mNothing to do.\\e[0m\"\n> fi\n> --------------------------------\n>\n> Are their any chances to get it integrated into Git?\n\nI like the idea and I'd be happy to review patches. :)\nAlso you may want to look at the C version that I provided\nabove and tell me why yours is better. ;)\n(Maybe the chosen defaults are saner, or such?)\n\n>\n> I tried to register that code as a Git alias, but git config complains about quote problem not showing where. It neither specifies if it's a single or double quote problem. Any advice on how to register that piece of code as an alias?\n\n(a) not using the alias system for everything:\n* You can define this as a (ba)sh function in e.g. .bashrc and then\njust call the shell function from the alias.\n* or you can put the code into an executable script \"git-NAME\" and\nthen the alias would be just \"git submodule foreach --recursive git\nNAME\"\n(b) define the function inside the alias, cf.\nhttps://www.atlassian.com/blog/git/advanced-git-aliases\n\n> If wished, I think I could expand the script to also recover hash values to Git tags if no branch was found.\n\nPersonally I do not think we should attach a HEAD to a tag in that case.\ntags are just like branches with special meaning, i.e. they are also\nin the refs/* hierarchy.  Note how git-checkout <tag> detaches from\nthe tag such that you do not modify the tag by default.\n\n>\n> Kind regards\n>     Patrick Lehmann\n"},{"id":"322574","messageId":"CAGZ79kY0gwk7KRY2iAVTXPBjPzx+mkciVWRR2z2cDgiBjQ2uuw@mail.gmail.com","threadId":"46207","inReplyTo":"0092CDD27C5F9D418B0F3E9B5D05BE080102887B@SBS2011.opfingen.plc2.de","subject":"Re: Restoring detached HEADs after Git operations","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-06-19T16:37:01Z","receivedAt":"2017-06-19T16:37:08Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Mon, Jun 19, 2017 at 2:52 AM, Patrick Lehmann\n<Patrick.Lehmann@plc2.de> wrote:\n> Hello Lars,\n>\n> for your questions:\n>> If there are multiple branches with the same hash then your script would pick the first one. Can you imagine a situation where this would be a problem?\n>\n> I can't think of a good solution to resolve it automatically. Maybe a script could print that there are multiple possibilities and it choose the first branch in the list.\n>\n>\n>> Plus, you are looking only at local branches. Wouldn't it make sense to look at remote branches, too?\n>\n> This is also related to restoring tags. If we go this way, we should have this priority list:\n> - local branches\n> - remote branches\n\nFor remote branches you would create a local branch of the same name\n(if such a branch would not exist, possibly setting it up to track that remote\nbranch)?\n\n> - tags\n\nas said in the other email and similar to remote branches, we'd not want to have\nHEAD pointing to them directly but somehow have a local branch.\n\n>> Submodule processing is already quite slow if you have many of them. I wonder how much this approach would affect the performance.\n>\n> Yes. It takes a few seconds to iterate all the submodules. It could be improved if the processing wouldn't be based on slow Bash scripts spawning lot's of sub-shells to execute multiple Git commands.\n\nHow many submodules are we talking about? (Are you on Windows to make\nshell even more fun?)\n"},{"id":"322575","messageId":"20170619170124.6oj6stoojds4srci@sigill.intra.peff.net","threadId":"46207","inReplyTo":"0092CDD27C5F9D418B0F3E9B5D05BE08010287DF@SBS2011.opfingen.plc2.de","subject":"Re: Restoring detached HEADs after Git operations","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2017-06-19T17:01:24Z","receivedAt":"2017-06-19T17:01:52Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Jun 19, 2017 at 08:46:45AM +0000, Patrick Lehmann wrote:\n\n>   for Branch in $(git branch --list | grep \"^  \" | sed -e \"s/  //\" ); do\n>     if [[ \"$(git rev-parse \"$Branch\")\" == $REF ]]; then\n>       echo -e \"  \\e[36mCheckout $Branch...\\e[0m\"\n>       git checkout $Branch\n>       FOUND=1\n>       break\n>     fi\n>   done\n\nI see Lars pointed you at for-each-ref, which is the preferred way for\nscripts to enumerate branches. But you can also use --points-at to skip\nthe inner part of your loop entirely, like:\n\n  git for-each-ref --points-at=HEAD --format='%(refname:short)' refs/heads\n\nThat should run much faster, as it only has to spawn one process rather\nthan one for each branch (it will print all of them, of course. You can\npipe through head -n 1 to get the first, and check out --sort if you\nwant to prioritize by recency or similar).\n\n-Peff\n"},{"id":"322578","messageId":"0092CDD27C5F9D418B0F3E9B5D05BE0801028A86@SBS2011.opfingen.plc2.de","threadId":"46207","inReplyTo":"CAGZ79kY0gwk7KRY2iAVTXPBjPzx+mkciVWRR2z2cDgiBjQ2uuw@mail.gmail.com","subject":"AW: Restoring detached HEADs after Git operations","fromName":"Patrick Lehmann","fromEmail":"patrick.lehmann@plc2.de","sentAt":"2017-06-19T17:34:12Z","receivedAt":"2017-06-19T17:34:21Z","isPatch":false,"sender":{"key":"patrick.lehmann@plc2.de","avatar":"https://gravatar.com/avatar/861fc81252f222aa3db2b3f869cde9d2a4759bd96bc31b40d01a1609a9e7d559?d=mp&s=160"},"body":"Hello,\n\nI'm just an advanced Git user, not a Git developer. So I might find some time to improve the suggested script, which I provided with the hints given on the mailing list, but I have no time to do a complete feature release in your patch based Git flow.\n\nI'm currently involved in 8 other open source projects. One can't improve the world alone by supplying patches to any open source project one is using...\n\nI have no experience with other shells then Bash. So if you rely on a Bash with less features, please port the syntax to such a shell system. (I personally do not support legacy programs or out-date programs).\n\n------\nWe are talking about circa 50 submodules in total with a maximum depth of 4. The platforms are:\n- Mint OS with Git in Bash\n- Windows 7 with Git-Bash\n- Windows 10 with Git-Bash\n- Windows 10 with Posh-Git\n\n\nKind regards\n    Patrick\n\n________________________________________\nVon: Stefan Beller [sbeller@google.com]\nGesendet: Montag, 19. Juni 2017 18:37\nBis: Patrick Lehmann\nCc: Lars Schneider; Git Mailinglist\nBetreff: Re: Restoring detached HEADs after Git operations\n\nOn Mon, Jun 19, 2017 at 2:52 AM, Patrick Lehmann\n<Patrick.Lehmann@plc2.de> wrote:\n> Hello Lars,\n>\n> for your questions:\n>> If there are multiple branches with the same hash then your script would pick the first one. Can you imagine a situation where this would be a problem?\n>\n> I can't think of a good solution to resolve it automatically. Maybe a script could print that there are multiple possibilities and it choose the first branch in the list.\n>\n>\n>> Plus, you are looking only at local branches. Wouldn't it make sense to look at remote branches, too?\n>\n> This is also related to restoring tags. If we go this way, we should have this priority list:\n> - local branches\n> - remote branches\n\nFor remote branches you would create a local branch of the same name\n(if such a branch would not exist, possibly setting it up to track that remote\nbranch)?\n\n> - tags\n\nas said in the other email and similar to remote branches, we'd not want to have\nHEAD pointing to them directly but somehow have a local branch.\n\n>> Submodule processing is already quite slow if you have many of them. I wonder how much this approach would affect the performance.\n>\n> Yes. It takes a few seconds to iterate all the submodules. It could be improved if the processing wouldn't be based on slow Bash scripts spawning lot's of sub-shells to execute multiple Git commands.\n\nHow many submodules are we talking about? (Are you on Windows to make\nshell even more fun?)\n"},{"id":"322581","messageId":"CAGZ79kbMOdkKiVsvxk4UeKKPicyi958LpomeY=ypXT0_=5d8BQ@mail.gmail.com","threadId":"46207","inReplyTo":"0092CDD27C5F9D418B0F3E9B5D05BE0801028A86@SBS2011.opfingen.plc2.de","subject":"Re: Restoring detached HEADs after Git operations","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-06-19T17:47:44Z","receivedAt":"2017-06-19T17:47:49Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Mon, Jun 19, 2017 at 10:34 AM, Patrick Lehmann\n<Patrick.Lehmann@plc2.de> wrote:\n> Hello,\n>\n> I'm just an advanced Git user, not a Git developer. So I might find some time to improve the suggested script, which I provided with the hints given on the mailing list, but I have no time to do a complete feature release in your patch based Git flow.\n\nok, thanks for letting us know. I may re-prioritize the \"reattach\nHEAD\" patches that I referenced earlier.\nI would have hoped that additionally to the shell lines you'd have\ngiven a good use case/summary.\n\n> I have no experience with other shells then Bash. So if you rely on a Bash with less features, please port the syntax to such a shell system. (I personally do not support legacy programs or out-date programs).\n>\n> ------\n> We are talking about circa 50 submodules in total with a maximum depth of 4. The platforms are:\n> - Mint OS with Git in Bash\n> - Windows 7 with Git-Bash\n> - Windows 10 with Git-Bash\n> - Windows 10 with Posh-Git\n\nThanks,\nStefan\n"},{"id":"322584","messageId":"xmqqefufuakk.fsf@gitster.mtv.corp.google.com","threadId":"46207","inReplyTo":"CAGZ79kY0gwk7KRY2iAVTXPBjPzx+mkciVWRR2z2cDgiBjQ2uuw@mail.gmail.com","subject":"Re: Restoring detached HEADs after Git operations","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-06-19T17:55:07Z","receivedAt":"2017-06-19T17:55:24Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Beller <sbeller@google.com> writes:\n\n> On Mon, Jun 19, 2017 at 2:52 AM, Patrick Lehmann\n> <Patrick.Lehmann@plc2.de> wrote:\n>> Hello Lars,\n>>\n>> for your questions:\n>>> If there are multiple branches with the same hash then your script would pick the first one. Can you imagine a situation where this would be a problem?\n>>\n>> I can't think of a good solution to resolve it automatically. Maybe a script could print that there are multiple possibilities and it choose the first branch in the list.\n>>\n>>\n>>> Plus, you are looking only at local branches. Wouldn't it make sense to look at remote branches, too?\n>>\n>> This is also related to restoring tags. If we go this way, we should have this priority list:\n>> - local branches\n>> - remote branches\n>\n> For remote branches you would create a local branch of the same name\n> (if such a branch would not exist, possibly setting it up to track that remote\n> branch)?\n>\n>> - tags\n>\n> as said in the other email and similar to remote branches, we'd not want to have\n> HEAD pointing to them directly but somehow have a local branch.\n\nLet's step back a bit.  We detach the HEAD for a good reason, no?\nWhy is it a good idea to move them back on to a branch picked among\nmultiple ones that all happen to be pointing at the same commit?\n\nThe user may build on a history of a submodule, and then may push\nthe result out to a particular branch at the other side; that is\nwhen being on a named branch in the submodule becomes useful, but\neven then I do not think randomly picking one branch and be on it\nis a good thing to do.\n\nI would understand the workflow would go more like so:\n\n - You do something at the superproject (e.g. create a new branch X\n   from an existing commit and check it out), which results in\n   submodules' HEADs getting detached at the commits bound to the\n   superproject's tree.\n\n - Because you want to make changes to both submodules and the\n   superproject in a consistent way, you'd want to commit changes to\n   all of these repositories and the push the result out in an\n   atomic way.\n\n - Hence you tell \"Hey, Git, I want all the submodules that I\n   modified to be on branch X\" from the superproject.\n\n   - This may succeed in a submodule where X is a new name, or the\n     current tip of branch X is an ancestor of the detached HEAD.\n\n   - This may fail in a submodule where there is branch X that does\n     not want to move to the detached HEAD's state.  In this latter\n     case, the user needs to deal with the situation (perhaps the\n     old X is expendable; perhaps the HEAD's commit may need to be\n     merged to old X; perhaps there are other cases).\n\nthough.\n"},{"id":"322586","messageId":"87r2yf97zf.fsf@gmail.com","threadId":"46207","inReplyTo":"0092CDD27C5F9D418B0F3E9B5D05BE08010287DF@SBS2011.opfingen.plc2.de","subject":"Re: Restoring detached HEADs after Git operations","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2017-06-19T17:56:36Z","receivedAt":"2017-06-19T17:56:45Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Mon, Jun 19 2017, Patrick Lehmann jotted:\n\n> Hello,\n>\n> I wrote a Bash script to recover branch names after Git operations have create detached HEADs in a Git repository containing lots of Git submodules. The script works recursively.\n>\n> I would like to see:\n> a) that script or algorithm being integrated into Git by default\n> b) that as a default behavior for all Git operations creating detached HEADs\n>\n> That's the command:\n> --------------------------------\n> git submodule foreach --recursive  'HEAD=$(git branch --list | head -n 1); if [[ \"$HEAD\" == *HEAD* ]]; then REF=$(git rev-parse HEAD); FOUND=0; for Branch in $(git branch --list | grep \"^  \" | sed -e \"s/  //\" ); do if [[ \"$(git rev-parse \"$Branch\")\" == $REF ]]; then echo -e \"  \\e[36mCheckout $Branch...\\e[0m\"; git checkout $Branch; FOUND=1; break; fi done; if [[ $FOUND -eq 0 ]]; then echo -e \"  \\e[31mNo matching branch found.\\e[0m\"; fi else echo -e \"  \\e[36mNothing to do.\\e[0m\"; fi'\n> --------------------------------\n>\n> How does it work:\n> 1. It uses git submodule foreach to dive into each Git submodule and execute a series of Bash commands.\n> 2. It's reading the list of branches and checks if the submodule is in detached mode. The first line contains the string HEAD.\n> 3. Retrieve the hash of the detached HEAD\n> 4. Iterate all local branches and get their hashes\n> 5. Compare the branch hashes with the detached HEAD's hash. If it matches do a checkout.\n> 6. Report if no branch name was found or if a HEAD was not in detached mode.\n>\n> The Bash code with line breaks and indentation:\n> --------------------------------\n> HEAD=$(git branch --list | head -n 1)\n> if [[ \"$HEAD\" == *HEAD* ]]; then\n>   REF=$(git rev-parse HEAD)\n>   FOUND=0\n>   for Branch in $(git branch --list | grep \"^  \" | sed -e \"s/  //\" ); do\n>     if [[ \"$(git rev-parse \"$Branch\")\" == $REF ]]; then\n>       echo -e \"  \\e[36mCheckout $Branch...\\e[0m\"\n>       git checkout $Branch\n>       FOUND=1\n>       break\n>     fi\n>   done\n>   if [[ $FOUND -eq 0 ]]; then\n>     echo -e \"  \\e[31mNo matching branch found.\\e[0m\"\n>   fi\n> else\n>   echo -e \"  \\e[36mNothing to do.\\e[0m\"\n> fi\n> --------------------------------\n>\n> Are their any chances to get it integrated into Git?\n>\n> I tried to register that code as a Git alias, but git config complains about quote problem not showing where. It neither specifies if it's a single or double quote problem. Any advice on how to register that piece of code as an alias?\n>\n> If wished, I think I could expand the script to also recover hash values to Git tags if no branch was found.\n\nI have something similar to this, this written before git-submodule\nlearned --branch (or at least before I knew about it):\n\n    $ git config alias.sm-pull-all\n    !git submodule foreach 'git checkout $(NAME=$name git sm-mainbranch) && git pull'\n    $ git config alias.sm-mainbranch\n    !git config --file ../.gitmodules submodule.$NAME.branch || git describe --all --always | sed 's!^heads/!!'\n\nSo with this I can run `git sm-pull-all` to update all the submodules in\na superproject to update them all. This relies on the branch name being\nin the .gitmodules config.a\n\nNow if you add a module with e.g. 'git submodule add -b master ...'\nyou'll have it checked out at the master branch, but I'm not familiar\nenough with all the workflows around them to say if there are any holes\nin that implementation.\n\nBut that seems like a fundimentally better approach to me than what\nyou're suggesting. Why would we try to work our way back from the SHA-1\nand guess what branch it lives on when we can just encode the branch\nname we'd like to be on in the superproject?\n"},{"id":"322594","messageId":"0092CDD27C5F9D418B0F3E9B5D05BE0801028B70@SBS2011.opfingen.plc2.de","threadId":"46207","inReplyTo":"CAGZ79kbMOdkKiVsvxk4UeKKPicyi958LpomeY=ypXT0_=5d8BQ@mail.gmail.com","subject":"AW: Restoring detached HEADs after Git operations","fromName":"Patrick Lehmann","fromEmail":"patrick.lehmann@plc2.de","sentAt":"2017-06-19T18:09:21Z","receivedAt":"2017-06-19T18:09:29Z","isPatch":false,"sender":{"key":"patrick.lehmann@plc2.de","avatar":"https://gravatar.com/avatar/861fc81252f222aa3db2b3f869cde9d2a4759bd96bc31b40d01a1609a9e7d559?d=mp&s=160"},"body":"Hello Stefan,\n\nthe use case is as follows:\n\nThe projects consists of circa 18 IP cores. Each IP core is represented by a Git repository. Think of an IP core as of a lonestanding DLL or SO file project. Each IP core references 2 submodules, which bring the verification environments for testing the IP core standalone.\n\nThese 18 IP cores are grouped to bigger IP cores, referencing the low-level IP cores and each again the 2 verification submodules. Finally, the main project references the bigger IP cores and again the 2 verification cores.\n\nTOPLEVEL\n  o- IP1\n       o- UVVM\n       o- VUnit\n  o- IP2\n       o- UVVM\n       o- VUnit\n  o- IP3\n       o- UVVM\n       o- VUnit\n  o- IP4\n       o- UVVM\n       o- VUnit\n       o- IP5\n           o- UVVM\n           o- VUnit\n       o- IP6\n           o- UVVM\n           o- VUnit\n       o- IP7\n           o- UVVM\n           o- VUnit\n  o- IP8\n       o- UVVM\n       o- VUnit\n       o- IP9\n           o- UVVM\n           o- VUnit\n       o- IP10\n           o- UVVM\n           o- VUnit\n  o- IP11\n       o- UVVM\n       o- VUnit\n       o- IP9\n           o- UVVM\n           o- VUnit\n       o- IP12\n           o- UVVM\n           o- VUnit\n   o- UVVM\n   o- VUnit\n\nThat's the simplified structure. I can't write more, because it's a closed source project. You can find other usecases e.g. in my other open source projects. E.g. The PoC-Library or The PicoBlaze-Library and the corresponding PoC-Examples repository.\n\nExample: PoC\nPile of Cores includes 4 Git submodules and is itself an IP core library.\nSo PoC-Examples again references PoC. This looks like this tree:\n\nPoC-Examples\n  |- lib/\n       o- PoC\n            |- lib\n                o- Cocotb\n                o- OSVVM\n                o- VUnit\n                     o- .... OSVVM\n                o- UVVM\n\nThe library VUnit itself already includes OSVVM as a library.\n\n----------------------\nForcast:\nI'll write a new question / idea about multiple equal submodules and the memory footprint soon...\nHere is my original question posted on StackOverflow: https://stackoverflow.com/questions/44585425/how-to-reduce-the-memory-footprint-for-multiple-submodules-of-the-same-source\n----------------------\n\nDo you need more use cases?\n\n\nKind regards\n    Patrick\n________________________________________\nVon: git-owner@vger.kernel.org [git-owner@vger.kernel.org]&quot; im Auftrag von &quot;Stefan Beller [sbeller@google.com]\nGesendet: Montag, 19. Juni 2017 19:47\nBis: Patrick Lehmann\nCc: Lars Schneider; Git Mailinglist\nBetreff: Re: Restoring detached HEADs after Git operations\n\nOn Mon, Jun 19, 2017 at 10:34 AM, Patrick Lehmann\n<Patrick.Lehmann@plc2.de> wrote:\n> Hello,\n>\n> I'm just an advanced Git user, not a Git developer. So I might find some time to improve the suggested script, which I provided with the hints given on the mailing list, but I have no time to do a complete feature release in your patch based Git flow.\n\nok, thanks for letting us know. I may re-prioritize the \"reattach\nHEAD\" patches that I referenced earlier.\nI would have hoped that additionally to the shell lines you'd have\ngiven a good use case/summary.\n\n> I have no experience with other shells then Bash. So if you rely on a Bash with less features, please port the syntax to such a shell system. (I personally do not support legacy programs or out-date programs).\n>\n> ------\n> We are talking about circa 50 submodules in total with a maximum depth of 4. The platforms are:\n> - Mint OS with Git in Bash\n> - Windows 7 with Git-Bash\n> - Windows 10 with Git-Bash\n> - Windows 10 with Posh-Git\n\nThanks,\nStefan\n"},{"id":"322597","messageId":"CAGZ79kYrEexbn1j46DQTNWhksFeU=WbvnP7gqiUoj4Uynduvkw@mail.gmail.com","threadId":"46207","inReplyTo":"xmqqefufuakk.fsf@gitster.mtv.corp.google.com","subject":"Re: Restoring detached HEADs after Git operations","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-06-19T19:11:47Z","receivedAt":"2017-06-19T19:12:10Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Mon, Jun 19, 2017 at 10:55 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Stefan Beller <sbeller@google.com> writes:\n>\n>> On Mon, Jun 19, 2017 at 2:52 AM, Patrick Lehmann\n>> <Patrick.Lehmann@plc2.de> wrote:\n>>> Hello Lars,\n>>>\n>>> for your questions:\n>>>> If there are multiple branches with the same hash then your script would pick the first one. Can you imagine a situation where this would be a problem?\n>>>\n>>> I can't think of a good solution to resolve it automatically. Maybe a script could print that there are multiple possibilities and it choose the first branch in the list.\n>>>\n>>>\n>>>> Plus, you are looking only at local branches. Wouldn't it make sense to look at remote branches, too?\n>>>\n>>> This is also related to restoring tags. If we go this way, we should have this priority list:\n>>> - local branches\n>>> - remote branches\n>>\n>> For remote branches you would create a local branch of the same name\n>> (if such a branch would not exist, possibly setting it up to track that remote\n>> branch)?\n>>\n>>> - tags\n>>\n>> as said in the other email and similar to remote branches, we'd not want to have\n>> HEAD pointing to them directly but somehow have a local branch.\n>\n> Let's step back a bit.  We detach the HEAD for a good reason, no?\n\nAnd the 'good reason' being that at the time git-submodule was written\nwe did not know what would be best, and having a detached HEAD\nwould be (a) easy to implement, and (b) removing one moving thing\nfrom the whole construction, hence making it a bit safer,\n(c) it sort of follows the mental model:\n\n    the superproject said it had the submodule at X\n        (and not at branch Y!)\n    the submodule itself is a whole repo on its own\n        (it doesn't need to be aware of the superproject)\n\nso in this world detaching at X is the best we can do.\n\n> Why is it a good idea to move them back on to a branch picked among\n> multiple ones that all happen to be pointing at the same commit?\n\nThis (rhetorical?) question reads like 2 questions actually:\n(a) \"Why is it a good idea to move them back on to a branch?\"\nIt makes working easier as the submodule is not detached,\nbut on a proper branch\n(b) \"picked among multiple ones that all ...\"\nI think this is a bad idea and we'd rather want to follow\nsome configuration instead of wild-guessing by Git.\n\n> The user may build on a history of a submodule, and then may push\n> the result out to a particular branch at the other side; that is\n> when being on a named branch in the submodule becomes useful, but\n> even then I do not think randomly picking one branch and be on it\n> is a good thing to do.\n\nso you provide one reason why it is useful, but then claiming it is\n'not a good thing' (yet). Can you give a reason why this is a 'bad thing'?\n\n> I would understand the workflow would go more like so:\n>\n>  - You do something at the superproject (e.g. create a new branch X\n>    from an existing commit and check it out), which results in\n>    submodules' HEADs getting detached at the commits bound to the\n>    superproject's tree.\n\nAnd here we'd want to discuss if we *really* want to detach the HEADs\nor rather have a symbolic ref \"following the superproject\".\n\n>  - Because you want to make changes to both submodules and the\n>    superproject in a consistent way, you'd want to commit changes to\n>    all of these repositories and the push the result out in an\n>    atomic way.\n\nCommitting and pushing are different things. You should not care if\nI commit atomically as you (in the general \"upstream\" sense)\ncannot observe my local commits.\n\nFor pushing we would want to have an atomic push, but that is\nnot the scope of this discussion. (As a Gerrit user, we implemented\nthe submodule atomicity serverside, but in plain Git server you'd\nnot need the atomicity either:\n\n    git commit -a -m \"update submodule pointers\"\n    git submodule foreach git push\n    git push\n\nshould be fine w.r.t. any non-atomic race condition.)\n\n>  - Hence you tell \"Hey, Git, I want all the submodules that I\n>    modified to be on branch X\" from the superproject.\n>\n>    - This may succeed in a submodule where X is a new name, or the\n>      current tip of branch X is an ancestor of the detached HEAD.\n\nso we'd allow fast forward for X. This seems arbitrary to me. I could\nalso say \"If X exists I allow a merge to be made between old X and\nthe object name given by the superproject\". (maybe as a config option)\n\n>    - This may fail in a submodule where there is branch X that does\n>      not want to move to the detached HEAD's state.  In this latter\n>      case, the user needs to deal with the situation (perhaps the\n>      old X is expendable; perhaps the HEAD's commit may need to be\n>      merged to old X; perhaps there are other cases).\n\nmakes sense.\n\n>\n> though.\n"},{"id":"322598","messageId":"CAGZ79kYB__LOK5MhK_OrXYL1xYgYW0Hk5XfjYfRWAcH_AJ78uQ@mail.gmail.com","threadId":"46207","inReplyTo":"0092CDD27C5F9D418B0F3E9B5D05BE0801028B70@SBS2011.opfingen.plc2.de","subject":"Re: Restoring detached HEADs after Git operations","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2017-06-19T19:21:36Z","receivedAt":"2017-06-19T19:21:52Z","isPatch":false,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Mon, Jun 19, 2017 at 11:09 AM, Patrick Lehmann\n<Patrick.Lehmann@plc2.de> wrote:\n> Hello Stefan,\n>\n> the use case is as follows:\n>\n> The projects consists of circa 18 IP cores. Each IP core is represented by a Git repository. Think of an IP core as of a lonestanding DLL or SO file project. Each IP core references 2 submodules, which bring the verification environments for testing the IP core standalone.\n\nSo phrased differently: You are using submodules to avoid \"DLL hell\"\n(sharing a lib, with ease of versioning as the submodules in the different IP\ncores may be pointing at different versions).\n\n>\n> These 18 IP cores are grouped to bigger IP cores, referencing the low-level IP cores and each again the 2 verification submodules. Finally, the main project references the bigger IP cores and again the 2 verification cores.\n>\n> TOPLEVEL\n>   o- IP1\n>        o- UVVM\n>        o- VUnit\n>   o- IP2\n>        o- UVVM\n>        o- VUnit\n>   o- IP3\n>        o- UVVM\n>        o- VUnit\n>   o- IP4\n>        o- UVVM\n>        o- VUnit\n>        o- IP5\n>            o- UVVM\n>            o- VUnit\n>        o- IP6\n>            o- UVVM\n>            o- VUnit\n>        o- IP7\n>            o- UVVM\n>            o- VUnit\n>   o- IP8\n>        o- UVVM\n>        o- VUnit\n>        o- IP9\n>            o- UVVM\n>            o- VUnit\n>        o- IP10\n>            o- UVVM\n>            o- VUnit\n>   o- IP11\n>        o- UVVM\n>        o- VUnit\n>        o- IP9\n>            o- UVVM\n>            o- VUnit\n>        o- IP12\n>            o- UVVM\n>            o- VUnit\n>    o- UVVM\n>    o- VUnit\n>\n> That's the simplified structure. I can't write more, because it's a closed source project. You can find other usecases e.g. in my other open source projects. E.g. The PoC-Library or The PicoBlaze-Library and the corresponding PoC-Examples repository.\n>\n> Example: PoC\n> Pile of Cores includes 4 Git submodules and is itself an IP core library.\n> So PoC-Examples again references PoC. This looks like this tree:\n>\n> PoC-Examples\n>   |- lib/\n>        o- PoC\n>             |- lib\n>                 o- Cocotb\n>                 o- OSVVM\n>                 o- VUnit\n>                      o- .... OSVVM\n>                 o- UVVM\n>\n> The library VUnit itself already includes OSVVM as a library.\n>\n> ----------------------\n> Forcast:\n> I'll write a new question / idea about multiple equal submodules and the memory footprint soon...\n> Here is my original question posted on StackOverflow: https://stackoverflow.com/questions/44585425/how-to-reduce-the-memory-footprint-for-multiple-submodules-of-the-same-source\n> ----------------------\n>\n> Do you need more use cases?\n>\n\nWell this use case points out a different issue than I hoped for. ;)\nFrom the stackoverflow post and from looking at the layout here,\none of the major questions is how to deduplicate the submodule\nobject store for example.\n\nBy use case I rather meant a sales pitch for your initial email:\n\n    I use this bash script because it fits in my workflow because\n    I need branches instead of detached HEADS, because $REASONS\n\nand I'd be interested in these $REASONS, which I assumed to be\n* easier to work with branches than detached HEADS (it aids the workflow)\n* we're not challenging the underlying mental model of tracking sha1s in\n  the superproject rather than branches.\n\nAt least I gave these reasons in the \"reattach HEAD\" stuff that I wrote,\nbut maybe there are others? (I know the code base of submodules very\nwell, but I do not work with submodules on a day-to-day basis myself...)\n"},{"id":"322608","messageId":"0092CDD27C5F9D418B0F3E9B5D05BE0801028CD6@SBS2011.opfingen.plc2.de","threadId":"46207","inReplyTo":"CAGZ79kYB__LOK5MhK_OrXYL1xYgYW0Hk5XfjYfRWAcH_AJ78uQ@mail.gmail.com","subject":"AW: Restoring detached HEADs after Git operations","fromName":"Patrick Lehmann","fromEmail":"patrick.lehmann@plc2.de","sentAt":"2017-06-19T20:13:57Z","receivedAt":"2017-06-19T20:14:05Z","isPatch":false,"sender":{"key":"patrick.lehmann@plc2.de","avatar":"https://gravatar.com/avatar/861fc81252f222aa3db2b3f869cde9d2a4759bd96bc31b40d01a1609a9e7d559?d=mp&s=160"},"body":"Hello Stefan,\n\nI never have tapped into the DLL Hell trap. That's maybe I never did C++ development or I started with VB .NET / C# as .NET solved major parts of the DLL Hell :). That doesn't mean my new beloved language Python doesn't have a similar problem ...\n\n\nThinking about DLL Hell is a thinking in big version numbers like 1.0, 2.0 oder even 2.1, 2.2, ...\nWe are here talking about revisions in the build numbers which need to be synchronized between the parent repository and the sub modules (IP cores). Both sides are under heavy development and interfaces evolving from day to day because hardware design can't be planned as easy as software design.\n\nSo by using Git submodules a developer - responsible for a submodule / IP core - can after he finished interface level 1 now go on and implement interface level 2. The parent project can finish it's integration and testing of the level 1 interface before proceeding with level 2. More over if the same IP core is used multiple time in different sub IP cores, it's possible to update one usage place to interface level 2 by a second developer so he can finish his IP core at level 2, which other usage places can still use the level 1 interface.\n\nStart situation:\n--------------------------------------\nTOPLEVEL (developer A)\n  o- IP_1 @level1 (developer B)\n       o- IP_2 @level1 (developer C)\n  o- IP_3 @level1 (developer D)\n       o- IP_2 @level1\n\n\nDeveloper C creates interface level 2, but all instances use level1 of IP_2:\n--------------------------------------\nTOPLEVEL (developer A)\n  o- IP_1 @level1 (developer B)\n       o- IP_2 @level1 (developer C)\n  o- IP_3 @level1 (developer D)\n       o- IP_2 @level1\n\n\nDeveloper D updates instance of IP_2 to level 2 and completes level 2 of IP_3:\n--------------------------------------\nTOPLEVEL (developer A)\n  o- IP_1 @level1 (developer B)\n       o- IP_2 @level1 (developer C)\n  o- IP_3 @level1 (developer D)\n       o- IP_2 @level2\n\nDeveloper A updates instance of IP_3 to level 2:\n--------------------------------------\nTOPLEVEL (developer A)\n  o- IP_1 @level1 (developer B)\n       o- IP_2 @level1 (developer C)\n  o- IP_3 @level2 (developer D)\n       o- IP_2 @level2\n\nDeveloper B has finished his testing for IP_1 and can now update the instance if IP_2:\n--------------------------------------\nTOPLEVEL (developer A)\n  o- IP_1 @level1 (developer B)\n       o- IP_2 @level2 (developer C)\n  o- IP_3 @level2 (developer D)\n       o- IP_2 @level2\n\n\nSo now imaging 8 developers, whereof 6 are working remote on the project. There is one responsible developer per IP core (maintainer) and an overall maintainer overseeing all integration merges and test results (CI).\n\n\nKind regards\n    Patrick\n\n________________________________________\nVon: Stefan Beller [sbeller@google.com]\nGesendet: Montag, 19. Juni 2017 21:21\nBis: Patrick Lehmann\nCc: Lars Schneider; Git Mailinglist\nBetreff: Re: Restoring detached HEADs after Git operations\n\nOn Mon, Jun 19, 2017 at 11:09 AM, Patrick Lehmann\n<Patrick.Lehmann@plc2.de> wrote:\n> Hello Stefan,\n>\n> the use case is as follows:\n>\n> The projects consists of circa 18 IP cores. Each IP core is represented by a Git repository. Think of an IP core as of a lonestanding DLL or SO file project. Each IP core references 2 submodules, which bring the verification environments for testing the IP core standalone.\n\nSo phrased differently: You are using submodules to avoid \"DLL hell\"\n(sharing a lib, with ease of versioning as the submodules in the different IP\ncores may be pointing at different versions).\n\n>\n> These 18 IP cores are grouped to bigger IP cores, referencing the low-level IP cores and each again the 2 verification submodules. Finally, the main project references the bigger IP cores and again the 2 verification cores.\n>\n> TOPLEVEL\n>   o- IP1\n>        o- UVVM\n>        o- VUnit\n>   o- IP2\n>        o- UVVM\n>        o- VUnit\n>   o- IP3\n>        o- UVVM\n>        o- VUnit\n>   o- IP4\n>        o- UVVM\n>        o- VUnit\n>        o- IP5\n>            o- UVVM\n>            o- VUnit\n>        o- IP6\n>            o- UVVM\n>            o- VUnit\n>        o- IP7\n>            o- UVVM\n>            o- VUnit\n>   o- IP8\n>        o- UVVM\n>        o- VUnit\n>        o- IP9\n>            o- UVVM\n>            o- VUnit\n>        o- IP10\n>            o- UVVM\n>            o- VUnit\n>   o- IP11\n>        o- UVVM\n>        o- VUnit\n>        o- IP9\n>            o- UVVM\n>            o- VUnit\n>        o- IP12\n>            o- UVVM\n>            o- VUnit\n>    o- UVVM\n>    o- VUnit\n>\n> That's the simplified structure. I can't write more, because it's a closed source project. You can find other usecases e.g. in my other open source projects. E.g. The PoC-Library or The PicoBlaze-Library and the corresponding PoC-Examples repository.\n>\n> Example: PoC\n> Pile of Cores includes 4 Git submodules and is itself an IP core library.\n> So PoC-Examples again references PoC. This looks like this tree:\n>\n> PoC-Examples\n>   |- lib/\n>        o- PoC\n>             |- lib\n>                 o- Cocotb\n>                 o- OSVVM\n>                 o- VUnit\n>                      o- .... OSVVM\n>                 o- UVVM\n>\n> The library VUnit itself already includes OSVVM as a library.\n>\n> ----------------------\n> Forcast:\n> I'll write a new question / idea about multiple equal submodules and the memory footprint soon...\n> Here is my original question posted on StackOverflow: https://stackoverflow.com/questions/44585425/how-to-reduce-the-memory-footprint-for-multiple-submodules-of-the-same-source\n> ----------------------\n>\n> Do you need more use cases?\n>\n\nWell this use case points out a different issue than I hoped for. ;)\nFrom the stackoverflow post and from looking at the layout here,\none of the major questions is how to deduplicate the submodule\nobject store for example.\n\nBy use case I rather meant a sales pitch for your initial email:\n\n    I use this bash script because it fits in my workflow because\n    I need branches instead of detached HEADS, because $REASONS\n\nand I'd be interested in these $REASONS, which I assumed to be\n* easier to work with branches than detached HEADS (it aids the workflow)\n* we're not challenging the underlying mental model of tracking sha1s in\n  the superproject rather than branches.\n\nAt least I gave these reasons in the \"reattach HEAD\" stuff that I wrote,\nbut maybe there are others? (I know the code base of submodules very\nwell, but I do not work with submodules on a day-to-day basis myself...)\n"}]}