Ignore new commits for git submodule
Asked Answered
A

6

95

Background

Using Git 1.8.1.1 on Linux. The repository looks as follows:

master
  book

The submodule was created as follows:

$ cd /path/to/master
$ git submodule add https://[email protected]/user/repo.git book

The book submodule is clean:

$ cd /path/to/master/book/
$ git status
# On branch master
nothing to commit, working directory clean

Problem

The master, on the other hand, shows there are "new commits" for the book submodule:

$ cd /path/to/master/
$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   book (new commits)
#
no changes added to commit (use "git add" and/or "git commit -a")

Git should ignore the submodule directory completely, so that the master is also clean:

$ cd /path/to/master/
$ git status
# On branch master
nothing to commit, working directory clean

Failed Attempt #1 - dirty

Inside the file master/.gitmodules is the following, as per this answer:

[submodule "book"]
        path = book
        url = https://[email protected]/user/repo.git
        ignore = dirty

Failed Attempt #2 - untracked

Changed master/.gitmodules to the following, as per this answer:

[submodule "book"]
        path = book
        url = https://[email protected]/user/repo.git
        ignore = untracked

Failed Attempt #3 - showUntrackedFiles

Edited master/.git/config to the following, as per this answer:

[status]
   showUntrackedFiles = no

Failed Attempt #4 - ignore

Added the book directory to the master ignore file:

$ cd /path/to/master/
$ echo book > .gitignore

Failed Attempt #5 - clone

Added the book directory to the master as follows:

$ cd /path/to/master/
$ rm -rf book
$ git clone https://[email protected]/user/repo.git book

Question

How can the book submodule be in its own repository directory under the master repository yet have git ignore the book submodule? That is, the following should not display:

#
#       modified:   book (new commits)
#

How to suppress that message when executing git status in the master repository?

An article about git submodule pitfalls suggests this an inappropriate submodule usage?

Asceticism answered 19/1, 2013 at 20:7 Comment(6)
You normally use submodules if you want to link the repository to a certain version of another repository, and keep track of that. But that does not seem what you want to to. You just want to use a repository inside another one, without tracking it. Don't add it as a submodule then.Gentlefolk
@FelixKling, if you add such repos that way and push it to GitHub, would it create just link for it without copying content of that folders?Theodicy
@Roland: Submodules are just files with a reference to the version of an other repository. Once they are initialized in a local copy of the repository, they are replaced by the actual content of the repository.Gentlefolk
I think you are looking for "ignore = all"Quechuan
With Git 2.13 (Q2 2017), you will be able to consider git config submodule.<name>.active false. See my answer belowAlsace
@Alsace does not work for submodules that are already checked out.Ornithosis
Z
63

To include another repository, that needn't be tracked in its super-repo, try this:

$ cd /path/to/master/
$ rm -rf book
$ git clone https://[email protected]/user/repo.git book
$ git add book
$ echo "book" >> .gitignore

Then commit.

As stated in the linked git submodule pitfalls article:

... the only linkage between the parent and the submodule is [the] recorded value of the submodule’s checked-out SHA which is stored in the parent’s commits.

That means that a submodule is not saved by its checked-out branch or tag, but always by a specific commit; that commit (SHA) is saved into the super-repo (the one containing the submodule) like a normal text file (it's marked as such a reference, of course).

When you check out a different commit in the submodule or make a new commit in it, the super-repo will see that its checked out SHA has changed. That's when you get the modified (new commits) line from git status.

To eliminate that, you can either:

  • git submodule update, which will reset the submodule to the commit currently saved in the super-repo (for details see the git submodule manpage; or
  • git add book && git commit to save the new SHA into the super-repo.

As mentioned in the comments, consider abandoning the book submodule: clone it inside the super-repo, if tracking of its state as part of the super-repo is not necessary.

Zora answered 20/1, 2013 at 7:17 Comment(1)
Wow, now I understand, why the supermodule needs to know the version of the submodule. Of course, it makes sense to do git add book && git commit. I did not realize that git can actually ensure that the two repos are in sync.Saleratus
S
123

Just run:

$ git submodule update

This will revert the submodule the to old commit (specified in parent-repo), without updating the parent-repo with the latest version of the submodule.

Speedometer answered 17/9, 2013 at 15:55 Comment(4)
No it's not, it won't change the status.Unsought
Why exactly would OP want to not have the latest from the book repository? I don't think your answer makes any sense in this context.Web
@AlexisWilke and if book interface change dramatically and OP don't have time to make changes in master repo?Wolbrom
can you do this while you're fixing conflicts during a merge?Showmanship
Z
63

To include another repository, that needn't be tracked in its super-repo, try this:

$ cd /path/to/master/
$ rm -rf book
$ git clone https://[email protected]/user/repo.git book
$ git add book
$ echo "book" >> .gitignore

Then commit.

As stated in the linked git submodule pitfalls article:

... the only linkage between the parent and the submodule is [the] recorded value of the submodule’s checked-out SHA which is stored in the parent’s commits.

That means that a submodule is not saved by its checked-out branch or tag, but always by a specific commit; that commit (SHA) is saved into the super-repo (the one containing the submodule) like a normal text file (it's marked as such a reference, of course).

When you check out a different commit in the submodule or make a new commit in it, the super-repo will see that its checked out SHA has changed. That's when you get the modified (new commits) line from git status.

To eliminate that, you can either:

  • git submodule update, which will reset the submodule to the commit currently saved in the super-repo (for details see the git submodule manpage; or
  • git add book && git commit to save the new SHA into the super-repo.

As mentioned in the comments, consider abandoning the book submodule: clone it inside the super-repo, if tracking of its state as part of the super-repo is not necessary.

Zora answered 20/1, 2013 at 7:17 Comment(1)
Wow, now I understand, why the supermodule needs to know the version of the submodule. Of course, it makes sense to do git add book && git commit. I did not realize that git can actually ensure that the two repos are in sync.Saleratus
Q
24

There are two kinds of change notices you can suppress (from git 1.7.2).

The first is untracked content which happens when you make changes to your submodule but have not yet committed those. The parent repository notices these and git status reports it accordingly:

modified: book (untracked content)

You can suppress these with :

[submodule "book"]
    path = modules/media
    url = https://[email protected]/user/repo.git
    ignore = dirty

However, once you commit those changes, the parent repository will once again take notice and report them accordingly:

modified:   book (new commits)

If you want to suppress these too, you need to ignore all changes

[submodule "book"]
    path = book
    url = https://[email protected]/user/repo.git
    ignore = all
Quechuan answered 21/10, 2014 at 9:47 Comment(5)
Imagine I've added ignore = all option to all submodules. Eventually some modules has new commits that was pushed. If somebody then clone super-repo, will it be on the old state of submodules or it will checkout the latest ones?Daven
With the command git clone --recursive git@... you will get the old state of the submodules. To update them, you will need something like git submodule foreach "git pull" after cloningQuechuan
Unfortunately, ignore = all option doesn't ignore the new commits of the submodule. I am running git version 1.7.1. Any idea way?Tews
I like this fix methodPringle
@Daven git submodule foreach --recursive "git pull --rebase" git submodule foreach --recursive "git checkout xxxBranch"Pringle
A
12

Git 2.13 (Q2 2017) will add another way to include a submodule which does not need to be tracked by its parent repo.

In the OP's case:

git config submodule.<name>.active false

See commit 1b614c0, commit 1f8d711, commit bb62e0a, commit 3e7eaed, commit a086f92 (17 Mar 2017), and commit ee92ab9, commit 25b31f1, commit e7849a9, commit 6dc9f01, commit 5c2bd8b (16 Mar 2017) by Brandon Williams (mbrandonw).
(Merged by Junio C Hamano -- gitster -- in commit a93dcb0, 30 Mar 2017)

submodule: decouple url and submodule interest

Currently the submodule.<name>.url config option is used to determine if a given submodule is of interest to the user. This ends up being cumbersome in a world where we want to have different submodules checked out in different worktrees or a more generalized mechanism to select which submodules are of interest.

In a future with worktree support for submodules, there will be multiple working trees, each of which may only need a subset of the submodules checked out.
The URL (which is where the submodule repository can be obtained) should not differ between different working trees.

It may also be convenient for users to more easily specify groups of submodules they are interested in as opposed to running "git submodule init <path>" on each submodule they want checked out in their working tree.

To this end two config options are introduced, submodule.active and submodule.<name>.active.

  • The submodule.active config holds a pathspec that specifies which submodules should exist in the working tree.
    • The submodule.<name>.active config is a boolean flag used to indicate if that particular submodule should exist in the working tree.

Its important to note that submodule.active functions differently than the other configuration options since it takes a pathspec.
This allows users to adopt at least two new workflows:

  1. Submodules can be grouped with a leading directory, such that a pathspec e.g. 'lib/' would cover all library-ish modules to allow those who are interested in library-ish modules to set "submodule.active = lib/" just once to say any and all modules in 'lib/' are interesting.
  2. Once the pathspec-attribute feature is invented, users can label submodules with attributes to group them, so that a broad pathspec with attribute requirements, e.g. ':(attr:lib)', can be used to say any and all modules with the 'lib' attribute are interesting.
    Since the .gitattributes file, just like the .gitmodules file, is tracked by the superproject, when a submodule moves in the superproject tree, the project can adjust which path gets the attribute in .gitattributes, just like it can adjust which path has the submodule in .gitmodules.
Alsace answered 16/4, 2017 at 17:53 Comment(10)
How to find the exact <name> for a sub-module in an existing project?Bunch
@Bunch Reading the config in the .gitmodules should help: https://mcmap.net/q/14045/-list-submodules-in-a-git-repositoryAlsace
Ah it's just the value from .git/config --> [submodule "<name>"]Bunch
Not work for me. Here is what I do: 1) git clone with --recursive; 2) set git config as answer; 3) do git checkout, git pull to checkout last submodule; Still get "(new commits)" .Orlop
@WuBaiquan What Git version are you using, on which OS?Alsace
@VonC, I am using git version 2.15.1 on Mac. git config -l "submodule.build_config.active=false" git status "modified: build_config (new commits)"Orlop
@WuBaiquan OK: it is best to ask a separate question, then, to study a bit more that particular case.Alsace
@Alsace I am using latest git version, and I did as you said. I opened the super-repository config file located in its .git folder and edited active = true to active = false. But still the changes to submodule can be committed and then it shows that the super-repository is dirty (and can be committed). Thus I am unable to ignore the commits from submodule.Danika
@Nikhil Yes, re-reading github.com/git/git/commit/…, I believe this would not work for existing submodules already checked out, but at the initial checkout of the parent repo, as in github.com/git/git/commit/….Alsace
@Alsace Before messaging to you, I tried both (with existing repo as well as new initialized repo) , for both cases it didn't work.Danika
W
2

Nevik Rehnel answer is certainly the correct one for what you are asking: I did not want to have a submodule, how the heck do I get out of that situation?!.

Only, if your master project requires the book submodule, it is a nice gesture to keep it as such because that way other users who checkout your project can then enjoy not having any special git command to run (well... there are some special commands to use submodules, but it still simpler to manage, overall, I think.)

In your case you make changes in the book repository and at some point you commit those changes. This means you have new commits in that submodule, which have a new SHA1 reference.

What you need to do in the master directory is commit those changes in the master repository.

cd /path/to/master
git commit . -m "Update 'book' in master"

This will updated the SHA1 reference in master to the newest version available in the book repository. As a result this commit allows others to checkout all of the master & book repositories at the tip.

So in effect you end up with one more commit whenever you make changes to a submodule. It is semi-transparent if you also make changes to some files in the master repository since you'd commit both at the same time.

Web answered 27/11, 2017 at 3:13 Comment(0)
K
-6

Run

git submodule update 

at the root level.

Kornher answered 30/1, 2014 at 22:53 Comment(2)
Just for anyone wondering. In my case (and OPs?), this doesn't change what git status says. It still thinks changes have happened.Mccain
It is very bad practice to clone other's answersNeptunian

© 2022 - 2024 — McMap. All rights reserved.