Search code examples
gitrepository

Clone git repositories and include the owner in the folder structure


I'm looking for a way to clone a git repository, e.g. from GitHub, and include the owner or organization in the folder structure of the download.

For example, when cloning repository angular-cli from organization angular in the current folder, I'd like to have it clone it like this in my current working directory: angular/angular-cli.

I have tried googling for a solution but couldn't find one, because basically all results where just telling me how to clone a repository. Of course I can do that, but I would like to have some tool that helps me automate this process. Maybe a bash or powershell script, or even something built into git directly.

Edit: In contrast to the other question, I'm looking for a tool that automatically places the repository in the right folder structure, based on the source, e.g. Github, and the user/organization e.g. Angular.


Solution

  • Update: As I just got a pleasant upvote of this old Q&A, I wanted to update my posting. I have recently begun to put this script into a PowerShell module (GitManagement) which can be found here: https://github.com/totkeks/PowerShell-Modules


    Built a solution in powershell myself. You can configure different Git providers by name and the regular expression that is used to parse the URL and build the corresponding path for the repository.

    <#
        .DESCRIPTION
        Clone git repositories including the project/user/organization/... folder structure
    #>
    Param(
        [parameter(Mandatory = $true)]
        [String]
        $Url
    )
    
    #------------------------------------------------------------------------------
    # Configuration of available providers
    #------------------------------------------------------------------------------
    $GitProviders = @{
        "Azure"  = {
            if ($args[0] -Match "https://(?:\w+@)?dev.azure.com/(?<Organization>\w+)/(?<Project>\w+)/_git/(?<Repository>[\w-_]+)") {
                return [io.path]::Combine($Matches.Organization, $Matches.Project, $Matches.Repository)
            }
        }
    
        "GitHub" = {
            if ($args[0] -Match "https://github\.com/(?<UserOrOrganization>\w+)/(?<Repository>[\w-_]+)\.git") {
                return [io.path]::Combine($Matches.UserOrOrganization, $Matches.Repository)
            }
        }
    }
    
    
    #------------------------------------------------------------------------------
    # Find the right provider and clone the repository
    #------------------------------------------------------------------------------
    $Match = $GitProviders.GetEnumerator() |
        Select-Object @{n = "Provider"; e = {$_.Key}}, @{n = "Path"; e = {$_.Value.invoke($Url)}} |
        Where-Object { $_.Path -ne $null } |
        Select-Object -First 1
    
    if ($Match) {
        Write-Host "Found match for provider: $($Match.Provider)"
    
        if ($Global:ProjectsDir) {
            $TargetDirectory = [io.path]::Combine($Global:ProjectsDir, $Match.Provider, $Match.Path)
        }
        else {
            Write-Error "No projects directory configured. Aborting."
        }
    
        git clone $Url $TargetDirectory
    }
    else {
        Write-Error "No match found for repository url: $Url"
    }