Home > Mobile >  How to change what git tracks
How to change what git tracks

Time:02-21

How do I make git move its tracking from the current directory, to that of a directory within the current directory. (What it is now)

/current_dir/
  /dir_i_want_to_track/
    ...
    ...

I want to track dir_i_want_to_track but right now its tracking current_dir (What I want)

/dir_i_want_to_track/
  ...
  ...

Edit for clarification @AD7six

These directories are within a repo. I started initializing the repo at /current_dir, and so git has been tracking all changes within /current_dir/. However, moving forward I want git to track all changes one directory deeper at /dir_i_want_to_track/, ignoring the other directories within /current_dir/., so that when I go onto the repo it only shows

/dir_i_want_to_track/
...

and not the other directories.

(I'd also like to keep a history of all previous commits)

CodePudding user response:

Do it slow and steady

The solution proposed here is the combination of 2 simple tasks that require no advanced git knowledge:

  • Move the git repository
  • Move files in a git repository

Consider the following, which simulates the state in the question:

mkdir -p /tmp/current_dir/dir_i_want_to_track
touch /tmp/current_dir/dir_i_want_to_track/README.md
cd /tmp/current_dir
git init
git add dir_i_want_to_track/README.md
git commit -m "Initial commit"

Here's our start state:

cd /tmp/current_dir
tree
.
└── dir_i_want_to_track
    └── README.md

1 directory, 1 file

Move the git repository

Git does not care what the path is to a local repository (except for some edge cases in older versions of git) - so just rename like you would any other folder. In this step we will rename current_dir such that it is current_dir/dir_i_want_to_track.

From the parent directory:

cd /tmp
mv current_dir current_dir_moved
mkdir current_dir
mv current_dir_moved current_dir/dir_i_want_to_track

That will achieve this intermediary state:

cd /tmp/current_dir
tree
.
└── dir_i_want_to_track
    └── dir_i_want_to_track
        └── README.md

2 directories, 1 file

Note that at this point current_dir is no longer a git repository.

Move files in a git repository

Moving files in git is done with git mv:

cd /tmp/current_dir/dir_i_want_to_track
git mv dir_i_want_to_track/* .
git commit -m "move everything one dir up"

Thus achieving our desired end state:

cd /tmp/current_dir/dir_i_want_to_track
tree
.
└── README.md
0 directories, 1 file

CodePudding user response:

Although there could be unexpected behaviors, you can do it this was:

  1. Make sure your repository is clean (make a commit if it's not).
  2. Move the hidden directory called .git and located in current_dir to dir_i_want_to_track.
  3. From your new repository, run a git add --all and a git commit -m "Change root of repo"

By doing that, your Git history will tell you you "moved" a bunch of files from a subdirectory to the main directory and that you deleted all the files located in the main directory.

CodePudding user response:

Try git filter-branch --subdirectory-filter. Say you are now on the branch foo.

# backup the current branch foo
git branch foo_backup 

# rewrite the branch foo
git filter-branch --prune-empty --subdirectory-filter dir_i_want_to_track

The branch foo gets rewritten. The commits that don't touch dir_i_want_to_track will be empty commits. In most cases, you don't want to keep them. --prune-empty instructs to remove these empty commits on the new branch.

git filter-branch gives a warning that suggests you use other tools like git filter-repo. So you could also try these tools.

After the new branch is created, you need to use git push --force origin foo:foo to update the branch foo in the remote repository. Make sure that no one else is updating foo while you are rewriting and uploading it, otherwise their work might get lost.

Update: as @AD7six pointed out, you may want to keep the history. If so, just make a new commit that tracks dir_i_want_to_track as the root directory.

# if you have run the previous commands and rewritten the branch, first go back to the previous foo.
# if not, skip the following command.
git reset foo_backup --hard

# create a new commit based on the current head and merge it
git merge $(git commit-tree -p HEAD -m "xxx" HEAD:dir_i_want_to_track)

# amend the commit message
git commit --amend

The git commit-tree part creates a new commit. Its parent is the foo head, its commit message is xxx and its root tree is the version of dir_i_want_to_track in the foo head. This way, the branch is not rewritten. Instead, it's just like that you remove all the other directories and files, move everything inside dir_i_want_to_track to the root directory of the repository, and then make a new commit.

  • Related