having trouble with a git sparse checkout (folder) - bash

here is my git server tree:
----a/
|--b/
|--c/
|--d/
|--e/
|--f/
|--g.txt
|--h.readme
here is my git version tree
---------------->master
|---->myBranch [files are up to date here]
here is my jenkins server tree
-----A/
|--B/
|--C/
I am trying to checkout the content of repository "e" in repository "B"
I just need the last version of the current branch i'm working on, and I don't want to commit, just to get some up-to-date read-only scripts to run, so depth 1 is okay I guess.
Anyway, The problem I'm facing is that I'm able to to a sparse checkout with
#############################
##### 1/ configuring local folder
#############################
git init
git config core.sparseCheckout true
#an empty repository with the remote is created:
git remote add -f origin ssh://guillaumedg#domain.com:port/myProjects/thisProject.git
#add repository "e" to be checked out:
echo e/*> .git/info/sparse-checkout
#############################
##### 2/ fetching/updating files
#############################
git fetch
git checkout myBranch
I know I'm close, but what I get is this:
-----A/
|--B/
| |----a/
| |--d/
| |--e/
| |--f/
| |--g.txt
| |--h.readme
|--C/
not this (which is what I want)
-----A/
|--B/
| |--f/
| |--g.txt
| |--h.readme
|--C/
any hints?
by the way I tried different ways of using "depth 1" for "step 2" with no success:
git fetch --depth 1 $(url) $(branch)
git checkout $(branch)
--> error: pathspec 'myBranch' did not match any file(s) known to git.
git fetch --depth 1 $(url) $(branch)
git checkout
--> fatal: You are on a branch yet to be born
git fetch --depth 1 $(url) $(branch)
git checkout -b $(branch)
fatal: A branch named 'myBranch' already exists.
git fetch
git checkout $(branch)
--> works as describe above

Git doesn't store directories, only files. So, given your drawing here:
----a/
|--b/
|--c/
|--d/
|--e/
|--f/
|--g.txt
|--h.readme
the repository has some commits that have files named:
a/d/e/f/g.txt
and:
a/d/e/h.readme
You can direct your Git to check out these specific files, using either command line options or the sparse checkout option you're attempting to use. Their names will still be a/d/e/f/g.txt and a/d/e/h.readme.
Your computer probably requires that these names be created by making a directory (or folders) named a, then making one named d in a, and so on. Git will do that. You cannot make Git use any other name for these files if you're going to use git checkout to extract them.1
So, that leaves you with the option of not using git checkout to get these files. You could get the commit (as you are doing already), then use git show on individual path names, for instance. The standard output of git show will show the file's contents; you can redirect this to a file name of your choice.
Since you don't want the whole repository, consider using git archive to turn one commit into an archive. Since you don't want the whole commit either, consider adding to this git archive command the name(s) of the file(s) that you want archived.2 You may then have an un-archiver that can skip the a/d/ part of the path names of each archived file. For instance, GNU tar has --strip-components.
1I think it would be nice to be able to remap stored file names to in-file-system names, for many reasons, including the case-folding issues and cheeky Linux programmers creating files named CON and LPT. :-) But Git can't, at least not today.
2This isn't required, and if you're downloading this kind of git archive from a hosting server such as GitHub, you may not be able to do that. But if you can do that, you'll save some amount of space and transfer time. Given your ssh://user#host URL, you can probably run ssh user#host "cd path/to/repo; git archive ..." and pipe the result to a local tar -xf -, for instance.

Related

How to check file/directory changes of a multi directory git repository between two git commits?

How to check file/directory changes of a multi directory git repository between two git commits?
In linux/bash we need to findout changes to a directory of multi-directory(e-store) git repository, say it has inventory-dir, order-dir, purchase-dir etc.., directories.
So basically after we do git pull we want to know in which folderes/directories files changes were made between present changes & last commit, and based on that output take an appropriate call.
We tried to use below git commands, but not sure that's the right way to proceed.
git diff inventory-dir
git log --name-status -2 inventory-dir
You might be looking for
git diff #^1
but to reduce the result to a tractable list of just file names you could add
--stat
or
--compact-summary
or merely
--name-only
Of those, my favorite is --compact-summary — it's tremendously informative while confining the output to one line per file. So then if you have a top-level directory myDirectory to which you wish to confine your attention, you would say
git diff --compact-summary #^1 -- myDirectory

Git: Push project folders into their repositories

I'd like to write a script that, when run, pushes all the last updated files into the matching GitHub repositories.
Here's what I tried:
myPath=absolute_project_path
for i in $*
do
if [[ -d $myPath/$i ]]
then
cd $myPath/$i
git add ./*
git commit -m "update"
git remote set-url origin https://usr:pwd#github.com/username/$i.git
git push -f -u origin main
fi
done
But this is adding all the folders to all the directories: so myrepo1 in GitHub, gets myrepo1+myrepo2 files, and myrepo2 gets myrepo1+myrepo2.
Does anybody know the reason why?
Notes on the workarounds tested, if needed: It seems that the staging needs to be emptied every time before changing file for another repository.
But i tried this also:
- Did a backup of my folders, then ran git rm -f, git add, git commit, git push (caused local folder to get deleted), re-copied from backup, and re-ran the script, but didn't help
- Also tried to manually remove all the folders on GitHub and re-push them, but caused Git to want me to do a Pull. But once the Pull has been done (which caused the deletion of my local files), a re-copy from backup and a new Push caused Git to ask to make a new Pull again... reason why of the push -f
It is only a suggestion, but for this you can use already existing tools like myrepo.
Simply register your repos:
mr register ~/gitHub/repo_1
mr register ~/gitHub/repo_2
...
then if you want to push all your repos, simply type:
mr push
if you wan to pull them all, type
mr update
an so on... read to doc.

How to identify if a recent pull had changes inside a directory

I currently have a git project with the structure:
z.txt
foo/a.txt
foo/b.txt
using bash how can I identify after running $ git pull that either a.txt and/or b.txt (i.e anything under the foo directory) have been altered?
A. If you already pulled
git diff
You can use git diff and specifically:
git diff commit1..commit2 --name-only; or
git diff commit1..commit2 --name-status
The following descriptions are from the doco.
--name-only
Show only names of changed files.
--name-status
Show only names and status of changed files. See the description of the --diff-filter option on what the status letters mean.
git pull tells you the commit ids it merges/fast-forwards:
/mnt/c/git/repo666 (develop)>git pull
Updating f86907f7a..a708dcfe8
In this case the command would be:
git diff f86907f7a..a708dcfe8 --name-status
git log
To see differences per commit you could use git log with --name-only or --name-status.
B. Before a pull
If you haven't pulled and you want a peek at the potential changes you can git fetch the branch (not pull) and compare the local copy of the remote branch your current branch.
/mnt/c/git/repo666(develop)>git fetch // not git pull
(...)
/mnt/c/git/repo666(develop)>git status
On branch develop
Your branch is behind 'origin/develop' by 3 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)
nothing to commit, working tree clean
/mnt/c/git/Platform (develop)>git diff develop origin/develop --name-status
(Please note I used git diff branch origin/branch and not git diff origin/branch so that is shown in the desired order i.e. if the file was added in origin/develop we want to see it as added not deleted.)
Note on git pull output
Please note that the output of git pull contains added and renamed files twice
Fast-forward
...
src/Folder1/Services/File1.cs | 30 +
src/Folder1/Services/File2.cs | 7 +
...
src/Folder1/ViewModels/XViewModel.cs | 8 +-
...
src/{Abc.Common/Services => Abc/Contracts/Area1}/Area1File1.cs | 7 +-
...
89 files changed, 7254 insertions(+), 4897 deletions(-)
create mode 100644 src/Folder1/Services/File1.cs
create mode 100644 src/Folder1/Services/File2.cs
...
rename src/{Abc.Common/Services => Abc/Contracts/Area1}/Area1File1.cs (83%)
...
We can get closer than what #tymtam suggests, if you're willing to do things before you run git pull.
Get the SHA for your current head and save it:
sha="$(git rev-parse HEAD)"
Next, run the pull:
git pull
Finally, compare foo on your new HEAD to what you had before:
git diff --stat $sha -- foo
Note, if you have uncommitted changes, those will be included in what git diff reports, so you can always run git stash before your diff command to hide them, and then git stash pop to get them back.

Git for Windows "No tags file" Response from "git diff" Command

Git version: 2.14.2.2
Whenever I run git diff on a repository I am greeted with the response No tags file. I have tried running the command on multiple repositories, multiple consoles (Cmd, PowerShell, MINGW64, Visual Studio Command Prompt) and all have the same response.
Strangely, the git log command also fails. Many other commands work, however, such as git status, git pull, etc. It seems to be only log and diff.
I have uninstalled Git entirely and reinstalled. Restarted my system. Tried referencing the git.exe directly (which yields the exact same response). Nothing is working and I have not seen this error anywhere else. I compared my user configs with those of a colleague and they are identical.
Some portion of the command executes properly, because if I supply two commit hashes, and I intentionally break one, the response I receive is:
It seems like another program may be hijacking the git diff command. I believe this because I'm not sure "No tags file" is even a possible Git response. Not sure what else it would be.
To make things even more confusing- my ultimate goal is to run the git diff within the context of an msbuild and it DOES EXECUTE CORRECTLY. Now, I could be satisfied with this, but I need to modify the diff command slightly, and running a full build each time is not productive, nor easy to troubleshoot. There is a task within the build script that runs an Exec command and it has no issues performing the diff. I'm also able to execute a Diff Against Current within SourceTree, which to the best of my knowledge, runs a git diff behind the scenes.
Any help would be very much appreciated.
:: Edits ::
Various commands:
git diff HEAD~1 HEAD
git diff master~1 master
git diff <commit-hash-1> <commit-hash-2>
git log HEAD~1..HEAD
git log master~1..master
git log <commit-hash-1>..<commit-hash-2>
Output:
Every one of the commands above returns the same No tags file response, in all of my repos.
Cat Head:
cd .git
cat HEAD
ls -R refs
Output:
New Repo:
mkdir testrepo
cd testrepo
git init
echo "file1" > file1.txt
git add .
git commit -m "initial commit of file1.txt"
echo "Hi there!" > file2.txt
git add .
git commit -m "added file2.txt"
git log
git diff HEAD~1 HEAD
Output:
git config -e:
git config --global -e:
::Edits 2::
I uninstalled all of my diffing/source control tools (SourceTree, Git, SVN, WinMerge, KDiff). Installed the portable version of Git. Opened CMD to a repo, put in full path to the git.exe portable and it still returned the No tags file response.
I also reviewed all of my path variables for: git, vim, ming, mintty and anything else that seemed suspect, but didn't find any.
I have restarted after performing all steps, and yet the problem persists.
::Edits 3::
I have a different user on my laptop, switched to that user and the git diff works properly, so clearly there is something with my main user that is conflicting. Will continue to look into my User directory for issues.
Here are the steps I'd take in this situation:
Try the following and check the response:
git diff HEAD~1 HEAD
git diff master~1 master
git diff <commit-hash-1> <commit-hash-2>
Try the same with log:
git log HEAD~1..HEAD
git log master~1..master
git log <commit-hash-1>..<commit-hash-2>
I'm actually guessing that your refs are messed up, which means that the direct hashes might work, but the HEAD and/or master one may not.
Look into the .git/refs folder
From the main repo folder:
cd .git
cat HEAD
ls -R refs
Hopefully, HEAD is pointing to a branch, and if master is checked out, cat HEAD output should look like:
ref: refs/heads/master
Then, the ls -R refs, should show a heads folder, with files for each of your local branches (i.e. master and possibly others). You also likely have refs/remotes and refs/tags directories.
If any of these things are radically different or missing, that could be your issue...
Since you have reinstalled git, create a brand new repo and try the same commands:
mkdir testrepo
cd testrepo
git init
echo "file1" > file1.txt
git add .
git commit -m "initial commit of file1.txt"
echo "Hi there!" > file2.txt
git add .
git commit -m "added file2.txt"
git log
git diff HEAD~1 HEAD
If this last one works, then git is likely working okay, but some tool you have is messing things up.
Post your config from git config -e and git config --global -e - maybe we can see something?
When googling for the "No tags file" message, the first results I get all talk about vi.
I do not understand why git would try to execute vi when running git diff or git log, could it be that your system is configured to use vi as a pager ?
# some possible places which could influence that :
echo $PAGER
echo $GIT_PAGER
git config --get core.pager
When digging in the documentation for less, I found that less can use a ctags file, to spot "the file that contains this tag".
So you can also look at the list of variables that influence the behavior of less :
# from bash :
# env will list all the defined environment variables
env
# the ones that impact 'less' should contain "LESS" in their names :
env | grep LESS

Windows custom git commands

Say I want a new git command, git new, that makes a new branch that is up to date with origin/master.
Is there a way I can make this script and have it available in all repositories on Windows from powershell?
edit: To clarify I want a git script not a powershell function. The only reason I mentioned powershell is because I don't use git bash.
Create a batch file that contains the following commands:
git branch %1 origin/master
git checkout %1
Save it, let's say, as C:\Scripts\new-branch.cmd. (I never worked with PowerShell, I don't know its rules. However, it should work as well using the old Windows Command Prompt).
Test the batch file works as expected by running:
C:\Scripts\new-branch.cmd test1
It should output something along these lines:
Branch test1 set up to track remote branch master from origin by rebasing.
Switched to branch 'test1'
Your branch is up-to-date with 'origin/master'.
If you don't need the new branch to track the remote branch then you just add --no-track to the git branch command.
If everything goes well then run:
git config --global alias.new "!C:/Scripts/new-branch.cmd"
This makes the Git alias new available to your Windows profile in all repositories. If you need it only in one repository then remove --global and run the command when the current directory is in the repository where you need it.
Use it as:
git new test2
You can use a git alias which uses git checkout:
git config --global alias.new 'checkout origin/master -b'
This would then be used as git new new_branch.
(Which is equivolent to git checkout origin/master -b new_branch
See the git docs for checkout. I tried the command and it worked, but when I looked at the docs, I didn't find a syntax that exactly matched my form. (Closest is git checkout [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>])
Note: #axiac, I may have used the !git because it doesn't hurt, and I may have needed to do multiple commands to solve the problem, and didn't remove it when I was done.

Resources