Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.5k views
in Technique[技术] by (71.8m points)

is it possible to save submodules changes to the main git index?

up until very recently i was managing modules via copy/paste but then i discovered submodules & with the single branch clone its becoming more sensible to use this feature.

however i have a couple of questions and hopefully someone could help me with them.

  1. is it possible to save a module changes in the main git index instead of the module it self ?

what i mean is am trying to have a central modules with the basic/essential setup on github & under each project that pull/require this module, the project can make changes that is related to him alone & save this changes to his git index, so we can clone the project later and all the changes will be there.

if this is not possible, what would be a viable alternative ?


# Partial Solution

use git diff --submodule=diff > modules_changes.diff & later simply use git apply modules_changes.diff

however this wont work with changed files "deleted/added files"

# Better Solution

setup a repo per module & have branches for each project


  1. how to auto set the module head on add ?

atm when you want to push something to the module while you are working on a project. the steps are usually

  • cd into the module dir
  • add & commit ur changes
  • push the new changes while specifying the head we will push to

however i was wondering if there is a way to automate that, so something like auto push on commit will work directly without the need to manually do the steps above on each module change.

question from:https://stackoverflow.com/questions/65867606/is-it-possible-to-save-submodules-changes-to-the-main-git-index

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The short answer is no: The only thing a superproject commit does is refer to some submodule commit by hash ID.

Remember that when using submodules, you're really just using two almost-totally-independent Git repositories. I say almost because the superproject refers to the submodule.

In the superproject, there's some instructions in the .gitmodules file. These instructions say how the superproject should run git clone. In particular, git clone needs a URL, and there is no place to store the URL in the commits:

  • A commit has metadata, including a tree line. The tree line refers to the hash ID of some internal tree object.
  • An internal tree object consists of "lines" (but in binary format; see git mktree and git ls-tree for the non-binary text formats). Each of these lines represents one record. Each record holds:
    • a mode, e.g., 100644 for a regular non-executable file;
    • a hash ID, e.g., c592dda681fecfaa6bf64fb3f539eafaf4123ed8; and
    • a pathname component, e.g., .clang-format.
  • The mode for a symbolic link is 120000, and the contents of the symlink are stored as a blob object.
  • The mode for a gitlink—a reference to a submodule—is 160000, and the hash ID in the tree entry is the commit hash ID in the submodule.

So there's only room for the hash ID, not the URL. Hence the URL is stored somewhere else (.gitmodules and/or your .git/config) in the superproject.

The name of the submodule is derived from the path, which in turn is derived from the tree object(s) used to reach the "gitlink" entry: the thing with mode 160000. That path corresponds to some directory in the superproject. Inside that directory, there should be a Git repository. If there isn't, git submodule init can use the URL (found wherever) to run git clone to populate that directory with a Git repository.

Once the repository is in place, the superproject can run:

(cd $path && git checkout $hash)

where $path is that path, and $hash is the hash in the gitlink. That hash ID had better be present in the clone! If it's not, the superproject checkout fails (and Git leaves you to clean things up yourself).

So, the superproject Git repository literally can't do anything but run git checkout, or a few other Git commands, in the submodule Git repository. If there were ways to run git apply on various patch files, that could do what you want, but that's not built-in to Git.

(Note that there are systems that do this sort of thing. One even uses Git: see guilt, which is built on quilt, which name came from the idea of stringing lots of patches together.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...