DEV Community

Liz Lam
Liz Lam

Posted on

Copy Your Modified Files in Git with 1 line

For one reason or another, I occasionally find myself in a place where I want to copy off all my modified files in my local git repository and start over. This is usually due to painful merges where I just want a fresh start. This is the one-liner you can use to do just that:

git status --porcelain=v1 | awk {'print $2'} | xargs -I {} cp -r {} ../dir_with_changed_files

Let's break down each part of this line in detail.

git status --porcelain=v1

You may be familiar with git status, adding the --porcelain=v1 flag just changes the output from this:

git status image

to this:

git status porcelain image

awk {'print $2'}

This awk command will print the 2nd column of standard out (i.e. what is printed on the screen). In our case, this will print out the column with the file names from the previous git status --porcelain=v1 command.

xargs -I {} cp -r {} ../dir_with_changed_files

This portion of the command utilizes the xargs tool which allows iteration over things coming from standard input. In this case, standard input for the xargs command is the standard output from the previous awk command. Which take the list of files and copies it to the ../dir_with_changed_files directory.

Top comments (8)

Collapse
 
basuradeluis profile image
basuradeluis

Interesting. I made up a similar command that uses 'tar' command to create a .tar(.zip) file, but in a dirty way. I would check that porcelain flag, when i can

Collapse
 
grepliz profile image
Liz Lam

Yeah, I feel like a lot of people come up with different solutions for this same problem. What is your command? It's always good to see different options.

Collapse
 
basuradeluis profile image
basuradeluis • Edited
tar cvf newFilename.tar `git status -s`

As I see now, "status -s" is similar to "status --porcelain".
My comand does not skip first column, so it will try add files "??" or "M" to the new .tar file, it will fail (and show a warning/error) as it will not find them, but it will continue with the other arguments.

Basically it is
tar cvf newFile.tar [list of file names separated with spaces]

DISCLAIMER TO EVERYBODY: my command is dirty and not tested. I dont take any responsability of anyone using it. Learn "tar cvf" and `` before using it :-)

Thanks for sharing, Liz, maybe i will try yours and/or the awk comand. Thanks

Thread Thread
 
grepliz profile image
Liz Lam

Ah I see you. Yes, you can do something similar like this:
git status -s | awk {'print $2'} | xargs -I {} tar -cvf newfile.tar {}

Thanks for sharing!

Collapse
 
sethiadhira profile image
sethiadhira

Pretty interesting!!
tried your approach, here the files which are renamed cannot be copied to the destination folder

Collapse
 
grepliz profile image
Liz Lam • Edited

Hmmm...this should work for renamed files. There may be an error for the original file that no longer exists, but that should not stop the command from working. What are you observing?

Collapse
 
sethiadhira profile image
sethiadhira • Edited

True, when you rename the file, eventually file does not exist hence the renamed file is not considered.
I added a small if-else(just for renamed files) in the above statement to make it work for my use case.

git status --porcelain=v1 | awk {' if ($1 == "R") print $4 ; else print $2'} | xargs -I {} cp -r {} modified_files/

Thread Thread
 
grepliz profile image
Liz Lam

Ah I see. You are actually doing a git mv to rename your files. Yes, you are right, in that case your solution is perfect! Thanks for sharing!