[git] git command to move a folder inside another

I have created a folder common with a bunch of source files and folders.

Now I want to move the common folder into the include folder so it looks like include/common

I tried these:

  1. git add include

  2. git mv common/ include/

    but it fails with this error

    fatal: bad source, source=myrepo/common, destination=myrepo/include

  3. I tried git mv common/ include/common but I get the same error

Any idea how to achieve this?

This question is related to git

The answer is


 git mv common include

should work.

From the git mv man page:

git mv [-f] [-n] [-k] <source> ... <destination directory>

In the second form, the last argument has to be an existing directory; the given sources will be moved into this directory.
The index is updated after successful completion, but the change must still be committed.

No "git add" should be done before the move.


Note: "git mv A B/", when B does not exist as a directory, should error out, but it didn't.

See commit c57f628 by Matthieu Moy (moy) for Git 1.9/2.0 (Q1 2014):

Git used to trim the trailing slash, and make the command equivalent to 'git mv file no-such-dir', which created the file no-such-dir (while the trailing slash explicitly stated that it could only be a directory).

This patch skips the trailing slash removal for the destination path.
The path with its trailing slash is passed to rename(2), which errors out with the appropriate message:

$ git mv file no-such-dir/
fatal: renaming 'file' failed: Not a directory

I solved this on windows by doing this:

  • Open Power shell console
  • run dir
  • Alt-click and drag over the file/folder name column, then copy
  • Paste to notepad++
  • run replace with regex: replace (.*) with git mv ".\\\1" ".\\<New_Folder_Here>\"
  • copy all text from notepad++ into powershell
  • hit enter

Another important note that I have missed, and fixed the "Bad Source" Error instantly:

(Just thought I will share my mistake just in case someone encounters it.. :))

Make sure the the correct path is selected in the git Console when you run the command:

- git mv Source Destination

If needed, use:

- cd SourceFolder

And then the mv command.


I had similar problem, but in folder which I wanted to move I had files which I was not tracking.

let's say I had files

a/file1
a/untracked1
b/file2
b/untracked2

And I wanted to move only tracked files to subfolder subdir, so the goal was:

subdir/a/file1
subdir/a/untracked1
subdir/b/file2
subdir/b/untracked2

what I had done was:

  • I created new folder and moved all files that I was interested in moving: mkdir tmpdir && mv a b tmpdir
  • checked out old files git checkout a b
  • created new dir and moved clean folders (without untracked files) to new subdir: mkdir subdir && mv a b subdir
  • added all files from subdir (so Git could add only tracked previously files - it was somekind of git add --update with directory change trick): git add subdir (normally this would add even untracked files - this would require creating .gitignore file)
  • git status shows now only moved files
  • moved rest of files from tmpdir to subdir: mv tmpdir/* subdir
  • git status looks like we executed git mv :)

you can use this script

# git mv a folder and sub folders in windows 

function Move-GitFolder {
    param (
        $target,
        $destination
    )
    
    Get-ChildItem $target -recurse |
    Where-Object { ! $_.PSIsContainer } |
    ForEach-Object { 
        $fullTargetFolder = [System.IO.Path]::GetFullPath((Join-Path (Get-Location) $target))
        $fullDestinationFolder = [System.IO.Path]::GetFullPath((Join-Path (Get-Location) $destination))
        $fileDestination = $_.Directory.FullName.Replace($fullTargetFolder.TrimEnd('\'), $fullDestinationFolder.TrimEnd('\'))

        New-Item -ItemType Directory -Force -Path $fileDestination | Out-Null

        $filePath = Join-Path $fileDestination $_.Name

        git mv $_.FullName $filePath
        
    }
}

Usage

Move-GitFolder <Target folder> <Destination folder>

the advantage of this solution over other solutions is that it move folders and files recursively in a folder and even create the folder structure if it doesn't exist


I had a similar problem with git mv where I wanted to move the contents of one folder into an existing folder, and ended up with this "simple" script:

pushd common; for f in $(git ls-files); do newdir="../include/$(dirname $f)"; mkdir -p $newdir; git mv $f $newdir/$(basename "$f"); done; popd

Explanation

  • git ls-files: Find all files (in the common folder) checked into git
  • newdir="../include/$(dirname $f)"; mkdir -p $newdir;: Make a new folder inside the include folder, with the same directory structure as common
  • git mv $f $newdir/$(basename "$f"): Move the file into the newly created folder

The reason for doing this is that git seems to have problems moving files into existing folders, and it will also fail if you try to move a file into a non-existing folder (hence mkdir -p).

The nice thing about this approach is that it only touches files that are already checked in to git. By simply using git mv to move an entire folder, and the folder contains unstaged changes, git will not know what to do.

After moving the files you might want to clean the repository to remove any remaining unstaged changes - just remember to dry-run first!

git clean -fd -n

Command:

$ git mv oldFolderName newFolderName

It usually works fine.

Error "bad source ..." typically indicates that after last commit there were some renames in the source directory and hence git mv cannot find the expected file.

The solution is simple - just commit before applying git mv.


Make sure you have added all your changes to the staging area before running

git mv oldFolderName newFoldername

git fails with error

fatal: bad source, source=oldFolderName/somepath/somefile.foo, destination=newFolderName/somepath/somefile.foo

if there are any unadded files, so I just found out.


Another way to move all files in a directory to a sub directory (keeps git history):

$ for file in $(ls | grep -v 'subDir'); do git mv $file subDir; done;


I'm sorry I don't have enough reputation to comment the "answer" of "Andres Jaan Tack".

I think my messege will be deleted (( But I just want to warn "lurscher" and others who got the same error: be carefull doing

$ mkdir include
$ mv common include
$ git rm -r common
$ git add include/common

It may cause you will not see the git history of your project in new folder.

I tryed

$ git mv oldFolderName newFolderName

got

fatal: bad source, source=oldFolderName/somepath/__init__.py, dest
ination=ESWProj_Base/ESWProj_DebugControlsMenu/somepath/__init__.py

I did

git rm -r oldFolderName

and

git add newFolderName

and I don't see old git history in my project. At least my project is not lost. Now I have my project in newFolderName, but without the history (

Just want to warn, be carefull using advice of "Andres Jaan Tack", if you dont want to lose your git hsitory.