7

If I wanted to make a directory and change directory into it all in one line, I could do something like this:

mkdir dir_name && cd $_

How can I do the same with git clone?

The command, git clone repo_url && cd $_, won't work obviously, because there's no such directory as repo_url. But is it possible to do it in one line?

Amir Shabani
  • 3,857
  • 6
  • 30
  • 67

6 Answers6

14

If you want to find the name automatically, you could try something like this:

git clone https://host.com/you/the-repo.git && cd "$(basename "$_" .git)"

That way you don't have to specify a folder name to git.

Explanation

$_

The underscore is a special bash variable that holds the last argument to the previous command.

Example: The following command will print 'C': touch "A" "B" "C" && echo "$_"

In the above git command, $_ will be https://host.com/you/the-repo.git

basename

Returns the base file name of a string parameter.

basename string [suffix]

The basename command reads the String parameter, deletes any prefix that ends with a / (slash) and any specified Suffix parameter, and writes the remaining base file name to standard output.

In the above git command, the basename command will return the-repo (which is what git will have named the repo it just cloned).

Brad Turek
  • 2,472
  • 3
  • 30
  • 56
NullDev
  • 6,739
  • 4
  • 30
  • 54
  • 1
    Consider simplifying it's usage further by adding it to a function in your `.bash_profile` arbitrarily named `gitclone` - in a similar way to [this answer](https://stackoverflow.com/questions/7131670/make-a-bash-alias-that-takes-a-parameter#answer-7131683). For example: **1)** Run the following command to append the `gitclone` function to your `.bash_profile` file: `echo $'\n'"function gitclone() { git clone \"\$1\" && cd \"\$(basename \"\$_\" .git)\" || return; }" >> ~/.bash_profile`. **2)** Create a new session and run the simplified command in the future: `gitclone "http://repo_url.git"` – RobC Dec 18 '19 at 14:48
  • @chepner Hi, can I ask the reason you edited this answer to put double quotes around `$(basename $_ .git)`? – Amir Shabani Dec 18 '19 at 15:52
  • 2
    I did that in the other answer; `$_` refers to the last argument of the previous command, and that answer made the desired directory name the last argument of the `git` command, so that the usage you asked about in your question would work. (The original would have worked fine as well, but just involved typing the directory name twice.) – chepner Dec 18 '19 at 15:56
  • @chepner Right, yes I got that, I made a mistake in my comment, fixed it. I meant the edit you did on this answer, when you put double quotes around `$(basename $_ .git)`. – Amir Shabani Dec 18 '19 at 16:00
  • 2
    That's just good practice, in case the full directory name contains any characters that would be subject to shell processing if left unquoted. (Actually, `$_` itself should be quoted as well; I'll fix that.) – chepner Dec 18 '19 at 16:04
  • 1
    If you're cloning from a repo url without `.git` at the end (like a github repo url for instance), remove the `.git` from the `basename` command – adamency Apr 20 '23 at 03:49
5

You can add a directory name for the git clone command:

git clone repo_url my_repo_dirname && cd "$_"
chepner
  • 497,756
  • 71
  • 530
  • 681
Frodon
  • 3,684
  • 1
  • 16
  • 33
4

I don't really like aliases with special names like cdls or gitclone because on a new system I can't remember the original commands. That's why I like the following solution for aliases:

## git extra features 
# - clone + cd 
function git() {
    if [ $1 = "clone" ]
    then 
        command git $@ && cd "$(basename "$_" .git)"
    else
        command git $@
    fi
}

Using command calls the original git command, not this one in the ~/.bashrc file.

Sy Ker
  • 2,047
  • 1
  • 4
  • 20
  • I LOVE IT!! For noobs like me: add this like so: `nano ~/.zshrc` and paste, reload setting with `zsh` – Herman Mar 02 '23 at 16:06
1

Add the following to your ~/.bashrc. Don't forget to source it!

function gccd { git clone "$1" && cd "$(basename $1 .git)"; }
export -f gccd

gccd stands for git clone and cd. This is the function equivalent of an alias. Now you can type: gccd <repo>. It will do exactly what you want.

Updated so that it works with both URL and with trailing .git. Thanks @kost

robmsmt
  • 1,389
  • 11
  • 19
  • This function doesn't work properly. It tries to `cd reponame.git` but should `cd reponame` – kost May 06 '22 at 19:30
  • 1
    `function gccd { git clone "$1" && cd "$(basename $1 .git)"; }` -- this one works – kost May 06 '22 at 19:35
  • I think i wrote this function a while back when it was more normal to clone a git repo with just the URL. Thanks I will update my function and answer – robmsmt May 08 '22 at 15:40
1

You can use the following

git clone http://repo_url.git && cd "!$:t:r"

Imp: Do not forget the double quotes in the cd command, else it won't work in some other shells or Git Bash in Windows.

How does it work?

The first command is the obvious git clone command. The second cd command is intriguing.

Now there is something called Word Designators for command history

  • !$ is the last part of the last command run

Here the last command run would be git clone http://repo_url.git. This command consists of three parts. 1. git, 2. clone and 3. http://repo_url.git. And http://repo_url.git is the last part. Hence !$ ==> http://repo_url.git

Then there is something called Word Modifiers, which modify the string preceding it.

  • :t removes all leading file name components, leaving the tail

So here !$:t would be read like (!$):t. Hence !$:t ==> repo_url.git

  • :r removes the trailing suffix from filenames like abcd.xyz, leaving abcd

So here !$:t:r would be read like {(!$):t}:r. Hence !$:t:r ==> repo_url

So it would cd to repo_url

To debug this yourself, use :p which just prints the command preceding it without executing it. Equivalent would be echo

Run the following in the exact sequence

  1. git clone http://repo_url.git
  2. !$:p ==> http://repo_url.git (or echo !$)
  3. !$:t:p ==> repo_url.git (or echo !$:t)
  4. !$:t:r:p ==> repo_url (or echo !$:t:r)
ontherocks
  • 1,747
  • 5
  • 26
  • 43
  • This looks promising, but does it really work? It uses history to read the last command, but when cloning, you do not have the command in history yet. – brablc Jan 22 '22 at 09:23
  • @brablc It will only work in interactive shells. So it won’t work in a Dockerfile, for example. – Diti Mar 23 '22 at 11:37
0

Bash function:

m.git.clone(){
    local url="${1}" dir="${2}"
    if [[ "${dir}" == "" ]]; then 
        dir="$(basename "${url}" .git)"
    fi
    
    git clone "${url}" "${dir}" && cd "${dir}"
}

Can be used:

m.git.clone git@github.com:user/path.to.git

Or

m.git.clone git@github.com:user/path.to.git customDir

Both work and cd only on success.

mjs
  • 21,431
  • 31
  • 118
  • 200