1

Before the question, a bit of back story:

So basically I was doing some major renovation of the comments in a vast number of source files in one of my projects and added a quick description about each file as a comment at the top of the files (along with many comments within the code itself).

I then decided having gone through and done that, that I would add additional information in the descriptors - such as author, date etc. So living on the edge I decided to do a find and replace in files using regex to select the full contents of the file and replace it with some extra info in the headers keeping everything that used to be in the file. As I am working in Verilog, there is an endmodule at the end of each file, so I used that as a marker to ensure I got everything in the regex.

Unfortunately, I forgot to add the endmodule back into the replace string, so basically in some hundred or so source files, I lost the line at the end. Not too much of an issue, it was easy to find-replace to put them back. Lesson learnt.


Anyway, I didn't realise this at first, so I spend an hour or so grouping the source files into a series of commits to my github repository. Fortunately, I noticed the endmodule issue before pushing those commits to origin, so I have been able to delete the commits using the git reset --soft HEAD~4 command to get rid of my 3 commits.

Now before I did that, I used the git show command to get the commit descriptions and a list of files included in each commit which I have now got saved in a text file. I was hoping to use these to recreate the commits having put all of the endmodule tags back.

But my powers of Google are letting me down this evening as I can't seem to find a way of making a commit containing all changes from a list of files. Ideally I would like some command I can run in the git shell (Windows Powershell) that will perhaps read a text file which contains a list of files. I then want all these files to be added to a new commit with the same message and extended description as before (these I can just copy and paste into whatever command).

Is there any way of doing this that is part of git, or do I need to get creative with powershell scripts?


I see from this SO question that you can use git commit [files] to create a new commit of only specific files. I presume I can add the -m switch to add a message as is customary. But how pipe in a list of files to replace [files].

For now I have just taken my list, manually turned it into a line and pasted it in to the command which has worked for me. But as you can see from the image below, this is clear very ugly.

enter image description here

I'm sure there must be a neater way of doing this, so even though my problem is now fixed, I'd still like to know for future reference if it is possible to perform the command where the [files] placeholder is replaced by the contents of a file which contains a filename on every line.

Community
  • 1
  • 1
Tom Carpenter
  • 539
  • 4
  • 18
  • `git add -u` will add all files for commit that are a) already being tracked and b) have been modified since the last commit – twalberg Apr 29 '15 at 15:25
  • @twalberg The trouble is I wanted the files in three separate commits which I had made. But because I had to do a soft reset, all of the files for the three commits are all tracked, so I need a way of separating them without having to go through and manually add each of the required files. – Tom Carpenter Apr 29 '15 at 16:05

2 Answers2

1

try (gc .\files.txt) -Join ", " to read all the lines from the file and return them as a comma separated list. you could nest that as part of your git commit:

edit - to surround each file path in double quotes and separate by space instead of comma (sorry, didn't think straight), based on your suggestion:

("""$((gc .\files.txt) -Join '" "')""")

alternatively use % { } (the ForEach-Object cmdlet with a script block) on the array before joining it.

(gc .\files.txt | % {'"{0}"' -f $_}) -Join " "

to make the final git command:

git commit ("""$((gc .\files.txt) -Join '" "')""") -m "Message" -m "Extended Description"
Vincent De Smet
  • 4,859
  • 2
  • 34
  • 41
  • `gc` is an alias for `Get-Content` which reads the contents of a file as an array, the default split is on the newline character. see `about_join`: https://technet.microsoft.com/en-us/library/hh847757.aspx see also `Get-Help about_join` – Vincent De Smet Apr 30 '15 at 23:21
  • 1
    This seems quite good. I've been experimenting with the join command as you showed. It seems if I do this ```git commit (""""+$((gc ..\files.txt) -Join """ """)+"""") -m "Message" -m "Extended Description"``` it will correctly load each line from the file, surround them all in double quotes (in case they have spaces in the file names), and have spaces between them, then send those to the git commit command as expected. If you add the above to your answer, I'll accept it as it nicely does what I need. – Tom Carpenter May 01 '15 at 05:00
  • thanks for the comment, I tried to cut down on the doublequotes interspersing single quotes where possible. Also no concat is needed as you can put expressions surrounded with `$(` and `)` within a double quote string. I tried to use `$q = [char]34` as well but it didn't make it more readable – Vincent De Smet May 01 '15 at 06:06
  • It does indeed look slightly neater with the fewer double quotes. – Tom Carpenter May 01 '15 at 14:07
0

I do not know so much about powershell, but if it has a command line tool like xargs, I'd suggest the following:

 xargs git commit < list_of_files

which is (mostly) equivalent to

 cat list_of_files | xargs git commit

Looking at other SO question and other SO question there is, unfortunately, no direct equivalent to xargs. But the Foreach function from the first link should provide an approximate experience. Unfortunately I do not have powershell and therefore can not provide a complete solution.

Community
  • 1
  • 1
Nils_M
  • 1,062
  • 10
  • 24