樱桃拣选适用于多个提交,但持续显示“您处于’分离的 HEAD’ 状态”消息。

huangapple go评论124阅读模式
英文:

Cherry pick works fine for multiple commits, but keeps giving a message "You are in 'detached HEAD' state"

问题

I have written a script, which takes 5 inputs:

  1. Clone URL
  2. BranchName to which the cherry pick needs to be merged
  3. The new branch name which needs to be created with all the cherry pick commits
  4. The cherryPick commit ids.
  5. Dynamically created temp directory in which these operations should happen.
#!/bin/bash

echo 'Start Cherry Pick'

cd $5 || exit

echo 'Switched to '$5
git clone $1 .
git checkout -f origin/$2
git checkout -b $3
git cherry-pick $4
git push origin HEAD
echo '***** SUCCESS *****'

This works well and creates a new branch on the $2 with name as $3 and prints ***** SUCCESS *****.

Start Cherry Pick, Switched to C:\Users******\Local\Temp\ae85a131-f783-4245-a5df-c4a54f6619b02426345661203195835,
Cloning into '.'..., Updating files: 29% (359/1216), Updating files: 30% (365/1216)Updating files: 31% (377/1216)Updating files: 32% (1180/1216)Updating files: 98% (1192/1216)Updating files: 99% (1204/1216)Updating files: 100% (1216/1216)Updating files: 100% (1216/1216), done.
Note: switching to 'origin/master'.,
You are in 'detached HEAD' state. You can look around, make experimental, changes and commit them, and you can discard any commits you make in this state without impacting any branches by switching back to a branch., If you want to create a new branch to retain commits you create, you may do so (now or later) by using -c with the switch command.
Example:, git switch -c , Or undo this operation with:, git switch -, Turn off this advice by setting config variable advice.detachedHead to false,
HEAD is now at 9a97592 Merge pull request #25 from gitUserName/CEAS-243,
Switched to a new branch 'CEAS-1234',
[CEAS-1234 ca9e831] should be ahead of master AccountManagerTest.cls, Date: Mon Apr 6 16:35:56 2020 +0530, 1 file changed, 1 insertion(+), 1 deletion(-),
[CEAS-1234 f7ab9df] should be ahead of master AccountProcessorTest.cls, Date: Tue Apr 7 00:06:26 2020 +0530, 1 file changed, 1 insertion(+), 1 deletion(-), remote: ,
remote: Create a pull request for 'CEAS-1234' on GitHub by visiting: ,
remote: https://github.com/gitUserName/gitRepoName/pull/new/CEAS-1234 ,
remote: , To https://github.com/gitUserName/gitRepoName.git, * [new branch]
HEAD -> CEAS-1234, ***** SUCCESS *****]

But let's say in any scenario if the script fails, like bad commit ids, or if the branch which is being created already exists, even then the Success is printed and even the same message this is printed You are in 'detached HEAD'....

Here is the output when the script fails:

Start Cherry Pick,
Switched to C:\Users\NAGESI~1\AppData\Local\Temp\b46aebc4-479a-43f0-a333-cebfad5b9e2a945082863319958458,
Cloning into '.'..., Updating files: 39% (475/1216), Updating files: 40% (487/1216)Updating files: 41% (499/1216)Updating files: 42% (1168/1216)Updating files: 97% (1180/1216)Updating files: 98% (1192/1216)Updating files: 99% (1204/1216)Updating files: 100% (1216/1216)Updating files: 100% (1216/1216), done.
Note: switching to 'origin/master'.,
You are in 'detached HEAD' state. You can look around, make experimental, changes and commit them, and you can discard any commits you make in this state without impacting any branches by switching back to a branch., If you want to create a new branch to retain commits you create, you may do so (now or later) by using -c with the switch command. Example:,
git switch -c , Or undo this operation with:, git switch -, Turn off this advice by setting the config variable advice.detachedHead to false,
HEAD is now at 9a97592 Merge pull request #25 from gitUserName/CEAS-243, Switched to a new branch 'CEAS-1234',
[CEAS-1234 f1e152e] should be ahead of master AccountManagerTest.cls, Date: Mon Apr 6 16:35:56 2020 +0530, 1 file changed, 1 insertion(+), 1 deletion(-),
[CEAS-1234 03c5681] should be ahead of master AccountProcessorTest.cls, Date: Tue Apr 7 00:06:26 2020 +0530, 1 file changed, 1 insertion(+), 1 deletion(-), To https://github.com/gitUserName/gitRepoName.git, ! [rejected]
HEAD -> CEAS-1234 (non-fast-forward),
error: failed to push some refs to 'https://github.com/gitUserName/gitRepoName.git', hint: Updates were rejected because the tip of your current branch is behind, hint: its remote counterpart. Integrate the remote changes (e.g., hint: 'git pull ...') before pushing again., hint: See the 'Note about fast-forwards' in 'git push --help' for details.,
***** SUCCESS *****


<details>
<summary>英文:</summary>
I have written a script, which takes 5 inputs:
1) Clone URL
2) BranchName to which the cherry pick needs to be merged
3) The new branch name which needs to be created with all the cherry pick commits
4) The cherryPick commit ids.
5) Dynamically created temp directory in which these operations should happen.
#!/bin/bash
echo &#39;Start Cherry Pick&#39;
cd $5 || exit
echo &#39;Switched to &#39;$5
git clone $1 .
git checkout -f origin/$2
git checkout -b $3
git cherry-pick $4
git push origin HEAD
echo &#39;***** SUCCESS *****&#39;
This works well and creates a new branch on the `$2` with name as `$3` and prints `***** SUCCESS *****`
Start Cherry Pick, Switched to C:\Users\******\Local\Temp\ae85a131-f783-4245-a5df-c4a54f6619b02426345661203195835, 
Cloning into &#39;.&#39;..., Updating files:  29% (359/1216), Updating files:  30% (365/1216)Updating files:  31% (377/1216)Updating files:  32%  (1180/1216)Updating files:  98% (1192/1216)Updating files:  99% (1204/1216)Updating files: 100% (1216/1216)Updating files: 100% (1216/1216), done.
Note: switching to &#39;origin/master&#39;., 
You are in &#39;detached HEAD&#39; state. You can look around, make experimental, changes and commit them, and you can discard any commits you make in this, state without impacting any branches by switching back to a branch., If you want to create a new branch to retain commits you create, you may, do so (now or later) by using -c with the switch command. 
Example:,   git switch -c &lt;new-branch-name&gt;, Or undo this operation with:,   git switch -, Turn off this advice by setting config variable advice.detachedHead to false, 
HEAD is now at 9a97592 Merge pull request #25 from gitUserName/CEAS-243, 
Switched to a new branch &#39;CEAS-1234&#39;, 
[CEAS-1234 ca9e831] should be ahead of master AccountManagerTest.cls,  Date: Mon Apr 6 16:35:56 2020 +0530,  1 file changed, 1 insertion(+), 1 deletion(-), 
[CEAS-1234 f7ab9df] should be ahead of master AccountProcessorTest.cls,  Date: Tue Apr 7 00:06:26 2020 +0530,  1 file changed, 1 insertion(+), 1 deletion(-), remote: , 
remote: Create a pull request for &#39;CEAS-1234&#39; on GitHub by visiting:        , 
remote:      https://github.com/gitUserName/gitRepoName/pull/new/CEAS-1234        , 
remote: , To https://github.com/gitUserName/gitRepoName.git,  * [new branch]      
HEAD -&gt; CEAS-1234, ***** SUCCESS *****]
But lets say in any scenario if the script fails, like bad commit ids, or if the branch which is being created already exists, even then the `Success is printed` and even the same message this is printed `You are in &#39;detached HEAD&#39;....`
Here is the output when script fails:
Start Cherry Pick, 
Switched to C:\Users\NAGESI~1\AppData\Local\Temp\b46aebc4-479a-43f0-a333-cebfad5b9e2a945082863319958458, 
Cloning into &#39;.&#39;..., Updating files:  39% (475/1216), Updating files:  40% (487/1216)Updating files:  41% (499/1216)Updating files:  42% (1168/1216)Updating files:  97% (1180/1216)Updating files:  98% (1192/1216)Updating files:  99% (1204/1216)Updating files: 100% (1216/1216)Updating files: 100% (1216/1216), done.
Note: switching to &#39;origin/master&#39;., 
You are in &#39;detached HEAD&#39; state. You can look around, make experimental, changes and commit them, and you can discard any commits you make in this, state without impacting any branches by switching back to a branch., If you want to create a new branch to retain commits you create, you may, do so (now or later) by using -c with the switch command. Example:,   
git switch -c &lt;new-branch-name&gt;, Or undo this operation with:,   git switch -, Turn off this advice by setting config variable advice.detachedHead to false, 
HEAD is now at 9a97592 Merge pull request #25 from gitUserName/CEAS-243, Switched to a new branch &#39;CEAS-1234&#39;, 
[CEAS-1234 f1e152e] should be ahead of master AccountManagerTest.cls,  Date: Mon Apr 6 16:35:56 2020 +0530,  1 file changed, 1 insertion(+), 1 deletion(-), 
[CEAS-1234 03c5681] should be ahead of master AccountProcessorTest.cls,  Date: Tue Apr 7 00:06:26 2020 +0530,  1 file changed, 1 insertion(+), 1 deletion(-), To https://github.com/gitUserName/gitRepoName.git,  ! [rejected]        
HEAD -&gt; CEAS-1234 (non-fast-forward), 
error: failed to push some refs to &#39;https://github.com/gitUserName/gitRepoName.git&#39;, hint: Updates were rejected because the tip of your current branch is behind, hint: its remote counterpart. Integrate the remote changes (e.g., hint: &#39;git pull ...&#39;) before pushing again., hint: See the &#39;Note about fast-forwards&#39; in &#39;git push --help&#39; for details., 
***** SUCCESS *****]
**So how can I print `success` only when the script is running fine and print error and error message if anything fails. 
Second, how to get rid of `You are in &#39;detached HEAD&#39; state.....` message.**
I tried : `$?` but it seems to only return exit code, so that may not be helpful much, in case of error and error message.
Just FYI : I am invoking this script from Java Ant Launcher:
Where my target is :
&lt;target name=&quot;git_multi_cherry_pick&quot;&gt;
&lt;echo message=&quot;START: MultiMerge&quot;/&gt;
&lt;exec executable=&quot;C:\Program Files\Git\bin\bash.exe&quot; osfamily=&quot;windows&quot; failonerror=&quot;true&quot;&gt;
&lt;arg value=&quot;${gitMultiCherryPick}&quot;/&gt;
&lt;arg value=&quot;${gitCloneURL}&quot;/&gt;
&lt;arg value=&quot;${gitBranchName}&quot;/&gt;
&lt;arg value=&quot;${gitNewBranchName}&quot;/&gt;
&lt;arg value=&quot;${cherryPickIds}&quot;/&gt;
&lt;arg value=&quot;${gitDirectory}&quot;/&gt;
&lt;/exec&gt;
&lt;exec executable=&quot;/bin/bash&quot; osfamily=&quot;unix&quot; failonerror=&quot;true&quot;&gt;
&lt;arg value=&quot;${gitMultiCherryPick}&quot;/&gt;
&lt;arg value=&quot;${gitCloneURL}&quot;/&gt;
&lt;arg value=&quot;${gitBranchName}&quot;/&gt;
&lt;arg value=&quot;${gitNewBranchName}&quot;/&gt;
&lt;arg value=&quot;${cherryPickIds}&quot;/&gt;
&lt;arg value=&quot;${gitDirectory}&quot;/&gt;
&lt;/exec&gt;
&lt;/target&gt;
And code to launch this target is 
Map&lt;String, String&gt; propertiesMap = new HashMap&lt;&gt;();
String uuid = String.valueOf(UUID.randomUUID());
Path tempDirectory = Files.createTempDirectory(uuid);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream buildXml = classLoader.getResourceAsStream(&quot;build/build.xml&quot;);
InputStream gitCherryPick = classLoader.getResourceAsStream(&quot;build/git-multi-cherry-pick.sh&quot;);
File buildFile = ConsumerHandler.stream2file(buildXml, &quot;build&quot;, &quot;.xml&quot;);
File cherryPick = ConsumerHandler.stream2file(gitCherryPick, &quot;git-multi-cherry-pick&quot;, &quot;.sh&quot;);
propertiesMap.put(&quot;gitMultiCherryPick&quot;, cherryPick.getName());
propertiesMap.put(&quot;gitCloneURL&quot;, &quot;https://myGitRepo.git&quot;);
propertiesMap.put(&quot;gitBranchName&quot;, &quot;master&quot;);
propertiesMap.put(&quot;gitNewBranchName&quot;, &quot;CEAS-1234&quot;);
propertiesMap.put(&quot;cherryPickIds&quot;, &quot;903f59d668e62e9950cb0616d39defde10a4730c 67faf443bf96e4b51f1d5eb0f93559d8c022e482&quot;);
propertiesMap.put(&quot;gitDirectory&quot;, tempDirectory.toFile().getPath());
List&lt;String&gt; sf_build = AntExecutor.executeAntTask(buildFile.getPath(), &quot;git_multi_cherry_pick&quot;, propertiesMap);
And `sf_build` returns with the output.
</details>
# 答案1
**得分**: 1
你正在检出一个远程分支(`origin/whatever`)。Git非常乐意遵从,但在此时并不会创建一个本地分支... 你会处于“分离的 HEAD”状态... 然后你运行你的操作,执行 `git push origin HEAD`,我认为你漏掉了目标分支。是不是应该是 `git push origin HEAD:$2`?最后,不要相信标准输出或错误输出来判断操作是否成功。请使用执行的退出代码来判断是否成功(0 = 成功。任何非零值 = 不成功)。
<details>
<summary>英文:</summary>
You are checking out a remote branch (`origin/whatever`). Git is more than happy to comply but a local branch is not created at that point... you are left in `detached HEAD` state.... and then you run your magic and do `git push origin HEAD` and I think your are missing the target branch. Is it rather `git push origin HEAD:$2`? Finally, do not trust std or err output to tell if the operation went well or not. Use the exit code of the execution to know if it was ok (0 = ok. Anything not 0 = not ok).
</details>
# 答案2
**得分**: 0
你的脚本使用了:
在`git clone`步骤之后紧跟着以下命令:
这里为什么使用了这个远程跟踪名称?这就是你进入“分离的 HEAD”模式的原因。
使用分离的 HEAD 模式没有任何问题,你的脚本的其余部分处理了这个模式,但如果你不想使用分离的 HEAD 模式,就不要要求使用分离的 HEAD 模式。
分离的 HEAD 模式的反义词是连接的 HEAD 模式,即当你处于一个分支名称上时。你可以通过以下方式实现:
- 创建一个新的分支名称,指向与`origin/$2`相同的提交,然后
- 切换到该分支名称
你可以使用以下一步完成的方式执行:
```bash
git checkout -B $2 origin/$2

这里可以移除 -f,因为没有理由使用 -f。这里使用大写的 B 的唯一原因是如果 $2 是远程仓库推荐的分支名称,这样你就已经在分支 $2 上了。如果远程仓库推荐的是 master 分支而你永远不会使用 master,可以使用 git checkout -b $2 origin/$2

如果你愿意,可以使用 git clone -b $2 来启动整个操作,这样你的克隆操作将以相当于 git checkout -b $2 origin/$2 结束。

但假设在任何情况下,如果脚本失败,比如提交 ID 不正确,或者正在创建的分支已经存在...

(正如已经注意到的,这里并没有创建任何分支。)

聪明的做法是检查每个Git命令的退出状态:

git clone ... || exit
git checkout ... || exit

等等。要做到等效的操作,可以在一系列命令之前设置e选项:

set -e

每个命令的失败现在都会导致整个脚本立即退出。

英文:

Your script uses:

git checkout -f origin/$2

right after the git clone step. Why did you use this remote-tracking name? That is why you are in "detached HEAD" mode.

There is nothing incorrect about using detached HEAD mode, and the rest of your script handles it, but if you don't want to use detached HEAD mode, don't ask for detached HEAD mode.

The opposite of detached HEAD mode is when you have an attached HEAD, i.e., when you are on a branch name. You would do this by:

  • creating a new branch name, pointing to the same commit as origin/$2, then
  • switching to that branch name

which you can do in one step with:

git checkout -B $2 origin/$2

You can remove the -f here as there should be no reason to use -f at all. The only reason to use uppercase B here is in case $2 is the branch name that the remote repository recommended, so that you are already on branch $2 like this. If the remote repository recommends master and you will never use master, you can use git checkout -b $2 origin/$2 instead.

If you like, you can use git clone -b $2 to kick the whole thing off, so that your clone operation ends with the equivalent of git checkout -b $2 origin/$2.

> But lets say in any scenario if the script fails, like bad commit ids, or if the branch which is being created already exists ...

(As already noted, no branch is being created.)

It's wise to check the exit status of each Git command:

git clone ... || exit
git checkout ... || exit

and so on. To do the equivalent, without the repeated || exit steps, you can set the e option:

set -e

before the series of commands, each of which will now cause the entire script to quit as soon as any command fails.

huangapple
  • 本文由 发表于 2020年4月8日 12:50:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/61093532.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定