1

I want to create a shell script that add, commit and push new or changed files to a repository. Currently, my script is doing this by iterating file by file, which takes too much time. My requirement is to still doing this file by file, but this time I just want to iterate over the new or changed files.

My shell script is as follows:

#!/bin/sh

CUR_DIR=$(pwd)
PROJECT_DIR="${CUR_DIR}"

for fileToCommit in $(find ${PROJECT_DIR}/* -type f);
do
  test -f "$fileToCommit" || continue
  printf "%s\n" "${fileToCommit}"
  git add "${fileToCommit}"
  git commit -a -m "[ADD] New ${fileToCommit##*/} File"
  git push
done

How can I do it in an effortless way?

Francisco Maria Calisto
  • 2,841
  • 4
  • 22
  • 54
  • 1
    Why file by file? Anyway, even with that odd requirement of one file per commit, you could at least get the push line out of the loop. Would still be long, but much faster. – Romain Valeri Oct 26 '21 at 09:25
  • Because of GitHub limitations. As my project is working with small size, yet a huge number of files per repository, I require a single file `commit`. Hence, I need to do it file by file. – Francisco Maria Calisto Oct 26 '21 at 09:28
  • Not sure, if you scale it for several files, it can break the pipe. Although you are right, it could be dangerous. Indeed, get the `push` outside the loop line will make things much faster. However, GitHub has limitations for the size of the `push` instruction. – Francisco Maria Calisto Oct 26 '21 at 09:33
  • 1
    I'll just suggest here that if you're working hard to defeat some GitHub restriction using some code to automate a way to sidestep that restriction, you're *probably* setting yourself up for future pain too, when GitHub close that particular workaround loophole. It makes more sense to contact GitHub support and find out why they have some particular restriction and what you can do to work *with them* to get past it, rather than sneaking around it... – torek Oct 26 '21 at 18:58

3 Answers3

2

From the git status documentation:

--porcelain[=<version>]
    Give the output in an easy-to-parse format for scripts.
    This is similar to the short output,
    but will remain stable across Git versions and regardless of user configuration.

This is the intended way to gather all changed/untracked/deleted files for scripts. It will give you an easy to parse output, still allowing you to handle all files individually if desired.

Furthermore, I think it would be wise to look into what porcelain means in git terminology. It will help you write reliable scripts across different git versions.

What does the term "porcelain" mean in Git?

A small example of how you can use this:

filesToPush=$(git status --porcelain | awk '{print $2}')

for file in $filesToPush; do
    # Your actions.
done

This example considers that you want to do the same actions for all files returned by git status. If you want different behavior for different file statuses (changed, deletion, untracked), you will need to extract column 1 as well and change behavior dependent on this.

How to get the second column from command output?

vsr
  • 173
  • 1
  • 10
1

Try this!

for file in $(git ls-files --others)
do
   git add $file
   git commit -m "adding $file ✅"
   git push -u origin main
done
Baimam Boukar
  • 908
  • 5
  • 20
1

Here's a oneliner:

for f in $(git status --porcelain | sed "s/^...//");do git add $f; git commit -sam "commit message - $f";done
h4r1337
  • 45
  • 6
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 04 '22 at 15:17