Search code examples
gitpowershellpipestdinmsysgit

Prevent PowerShell from "boxing" program output


I'm trying to run the following command in PowerShell:

git log --cherry-pick master...branch --format=%h | git cherry-pick -n --stdin

git log yields a newline-delimited list of commit hashes, which I then want to pass to git cherry-pick. However, git cherry-pick always complains:

'atal: bad revision '12abcdef

where 12abcdef is the first line returned by git log. Note, the above is not a typo - the output really is mangled like that.

The issue appears to be that PowerShell is transforming the git log output into an array of strings and then trying to pipe that through to git cherry-pick, which pukes because it doesn't know about PS objects; it just expects raw text from stdin. I'm guessing this is related to the mangled output I'm seeing above, but I'm not sure.

If I run the same command via cmd.exe or git bash, everything works as expected. I've tried various PS commands on the git log output to try to get it to remain raw (join, out-string, etc.) but nothing has worked.

So, is there a way to tell PowerShell to leave stdout alone (i.e. just let it be "raw"), or am I doing something wrong, or is there a PowerShell-y way I should be doing this that will give me the desired result?


Solution

  • Assuming git log --cherry-pick works like I expect it would, the most PowerShell-like way to do this would probably be something like this:

    foreach ($cherry in $(git log --cherry-pick master...branch --format=%h)) {
        git cherry-pick -n $cherry
    }
    

    Or like this:

    git log --cherry-pick master...branch --format=%h | ForEach-Object {
        git cherry-pick -n $_
    }
    

    Or if you have to be terse:

    git log --cherry-pick master...branch --format=%h | % { git cherry-pick -n $_ }
    

    I doubt there's a way to do it with pipelines that's very clean because Unix pipelines are character streams while PowerShell pipelines are objects. You're not going to be able to change how the pipeline operator in PowerShell works.