0

Let's say I've got the following directory structure.

.ProjectFolder
|-A
|-B
|-C

Where A,B and C are all github projects.

I could do

git submodule foreach git checkout <branch> && git submodule foreach git pull

to checkout and pull each one to the most recent version of . However, let's say that I have some work done on A locally, and git will tell me that it cannot check out to because of my uncommited work.

I would like to write a bash script that goes inside of each folder, checks out said branch if possible, then performs a set of actions. Say

for item in $(ls);do
  cd ./$item 
  git checkout <branch>
  git pull
  cd ..
done

The issue with that is "cd". When I try doing that, it doesn't seem to go into the folder. I've browsed a bit around and I've seen that happens because "cd" runs a subshell, then exits, leaving me in the same place as before. I've tried sourcing the file rather than running it, and that didn't seem to work either.

Does anybody have any alternative? (preferably, alternatives that don't use aliases for "cd").

The reason why i'd like to do it this way is because I'd like to extend that functionality at some point I.E. checkout to a new local branch, commit the changes to that branch, then attempt to checkout the branch I was interested in.

2
  • I've seen that happens because "cd" runs a subshell this is not true - please update the question to show the error message you are seeing or more precisely describe the problem. Commented Jun 7, 2022 at 13:16
  • 1
    The problem is when you use cd in a subshell that subsequently exits, not that cd spawns a subshell. Commented Jun 7, 2022 at 13:22

3 Answers 3

2

When I try doing that, it doesn't seem to go into the folder...

If I have the same project structure:

$ tree ProjectFolder
ProjectFolder/
├── A
├── B
└── C

And inside that folder I run your script, but I replace the git commands with pwd, we can see that it works exactly as intended:

$ cd ProjectFolder
$ for item in $(ls); do
> cd ./$item
> pwd
> cd ..
> done
.../ProjectFolder/A
.../ProjectFolder/B
.../ProjectFolder/C

So we know the cd is working. If we run the git commands instead, it also seems to work:

$ for item in $(ls); do
> cd ./$item
> git checkout testbranch
> git pull
> cd ..
> done
branch 'testbranch' set up to track 'origin/testbranch' by rebasing.
Switched to a new branch 'testbranch'
Already up to date.
branch 'testbranch' set up to track 'origin/testbranch' by rebasing.
Switched to a new branch 'testbranch'
Already up to date.
branch 'testbranch' set up to track 'origin/testbranch' by rebasing.
Switched to a new branch 'testbranch'
Already up to date.

That also seems to work.

I would make suggest a few changes to your script:

  • Don't use ls; just use wildcard expansion:

    for item in *; do
    
  • Consider some defensive coding to make sure your targets are git repositories:

    for item in *; do
      [ -d "$item/.git" ] || continue
    done
    

    This prevents your script from breaking or throwing up errors if ProjectFolder contains files or non-git-repository directories.

  • You don't need to use cd at all if you use the -C option to git:

    for item in *; do
      [ -d "$item/.git" ] || continue
      git -C "$item" git checkout testbranch
      git -C "$item" git pull
    done
    
Sign up to request clarification or add additional context in comments.

Comments

0

I tried your script in git bash and it worked. To avoid cd, we have at least 2 options.

One is to export GIT_DIR and GIT_WORKTREE,

for item in $(ls);do
  export GIT_DIR=${item}.git
  export GIT_WORKTREE=${item}
  git checkout <branch>
  git pull
done
unset GIT_DIR
unset GIT_WORKTREE

The other is to use --git-dir and --work-tree,

for item in $(ls);do
    git --git-dir=${item}.git --work-tree=${item} checkout <branch>
    git --git-dir=${item}.git --work-tree=${item} pull
done

In order to run the script in any directory, it's better to pass the absolute paths to gitdir and worktree.

Comments

0

I using in my progect with couple of microservices this build branch script: https://github.com/stemax/branch_builder

Just downloaded into parent folder and set main branch and subfolders.

2 Comments

A link to an external source is not considered a good answer. Providing a short snippet from your github repo would be more helpful :)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.