git command to move a folder inside another
GitGit Problem Overview
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:
-
git add include
-
git mv common/ include/
but it fails with this error
> fatal: bad source, source=myrepo/common, destination=myrepo/include
-
I tried
git mv common/ include/common
but I get the same error
Any idea how to achieve this?
Git Solutions
Solution 1 - Git
One of the nicest things about git is that you don't need to track file renames explicitly. Git will figure it out by comparing the contents of the files.
So, in your case, don't work so hard: Ref: Git mv docs
$ mkdir include
$ git mv common include
$ git rm -r common
$ git add include/common
Running git status
should show you something like this:
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# renamed: common/file.txt -> include/common/file.txt
#
Solution 2 - Git
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
Solution 3 - Git
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
.
Solution 4 - Git
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.
Solution 5 - Git
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.
Solution 6 - Git
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 thecommon
folder) checked into gitnewdir="../include/$(dirname $f)"; mkdir -p $newdir;
: Make a new folder inside theinclude
folder, with the same directory structure ascommon
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
Solution 7 - Git
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;
Solution 8 - Git
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 moves folders and files recursively and even creates the folder structure if it doesn't exist.
Solution 9 - Git
Move your files and use git stage
You can move your files using your favorite tools (command line, graphical file explorer) and git will figure out that you made move instead of deletion and creation once you staged your operations, as suggested by @Andres but if you make too many modifications, as Erik Kaplun pointed out, explicit git mv
could help.
Stage is not used in some applications
Some GUI git tools like GitHub Desktop does not provide direct access to stage: you can select and deselect modifications, but it does not modify the underlying git stage. You need to use a more powerful git tool, like the command-line tool or the authentic git GUI to stage the changes, then GitHub Desktop too will show the operation as rename.
Solution 10 - Git
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 executedgit mv
:)
Solution 11 - Git
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.
Solution 12 - Git
If you are using GitLab
, its integrated Web-IDE, can be used for some file management tasks including move and rename ( without local clone )
Click on Web-IDE on the repository main window.
Right click on the folder and select Rename/Move
( for example moving src
to foo/bar/src
). The changes will be shown in the web-ide.
Remember to commit!
Solution 13 - Git
With Git Tortoise
it is very easy.
Right drag source to destination ( select source, hold the right mouse key, drag to destination, release mouse ) .
A menu will be displayed which has Git Move versioned items
and Git Move and rename versioned items
.
Of course the git repo should be cloned locally
Solution 14 - Git
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
(.*)
withgit mv ".\\\1" ".\\<New_Folder_Here>\"
- copy all text from notepad++ into powershell
- hit enter