Why isn't git reading the added file? - linux

I was reading an article that told me to add a file and place it in my path. Not knowing what the author meant by path, i simply put it in my root directory.
Trying to run 'git diffall', git says diffall is not a command, any ideas? Thanks in advance.
The article snippet for more information:
Write the following code to a file called git-diffall and place in your path (I put it in >…/my-git-install-dir/cmd/ )
#!/bin/sh
git diff --name-only "$#" | while read filename; do
git difftool "$#" --no-prompt "$filename" &
done
And run it in git (with usual diff input parameters), for example:
git diffall
git diffall HEAD

your 'path' is the collection of directories where the system looks for executables. To see it, simply execute echo $PATH at the commandline. Then put your script in one of those directories.

Related

How to source the files to be added to a git repo from a file?

I want to always add the same files to my git repo, and I thought that having a file of files to add to git would be an easy way to do that.
How can I ask git add to read the files to be added from a file?
It is also easy to use standard cli tools to do this :
# bash:
git add $(cat file)
# xargs is standard on linux, and comes with git-bash on Windows :
cat file | xargs git add
It seems that git add --pathspec-from-file=file is just what I was looking for.
Just make sure that all lines are valid file names. And that none are empty.

Alias Multiple Commands in Linux

I am managing a website using git. One of the requirements for the git repository is that bare = true. It uses a post-receive hook to manage pushes from my local computer. The problem is that sometimes I would like to make changes to a WordPress directory on my website using the wp-admin view online. So then I would just ssh into the directory and run git --work-tree="BLAH" add . and git --work-tree="BLAH" commit -m "BLAH". Is there a way to set up an alias, like alias git="git --work-tree=\"BLAH\"" and have that work for all git commands?
There are times when alias are a great tool. Then there are times when things start getting too complicated where a shell script is better.
To create a single command that executes other commands just create a file (maybe call it git-add-all) then type the following:
#! /bin/bash
git --work-tree="BLAH" add .
git --work-tree="BLAH" commit -m "BLAH"
Then you can run the script by simply doing:
bash git-add-all
Even better, make the script executable:
chmod +x git-add-all
Then you can use it like any command:
./git-add-all
Advanced tips:
To be able to run the script from any git directory you can copy/move the file to one of the directories in your $PATH. For example /usr/loca/bin. Then you can simply run git-add-all instead of ./git-add-all.
Even better is to create your own personal scripts directory and include it in $PATH. I personally use ~/bin. To add the directory to $PATH you just need to add the following to .bashrc or .profile:
export PATH=/home/username/bin:$PATH
or if you're doing this for the root user:
export PATH=/root/bin:$PATH
In case anyone is curious how I solved it (thanks to shellter's comment), I wrote a bash script then prompted the user for input like so:
#!/bin/bash
function fix {
git --work-tree="PATH_TO_WORKING_TREE" $1
}
echo -n "git "
read -e INPUT
until [ "$INPUT" = "quit" ]; do
fix $INPUT
echo -n "git "
read -e INPUT
done
Running it:
user#server [repo.git] $ git-fix
git status
# On branch master
nothing to commit (working directory clean)
git quit
There is a .bashrc file in Linux. You can edit it for creating alias for your favorite and frequently used commands.
To create an alias permanently add the alias to your .bashrc file
gedit ~/.bashrc
The alias should look like:
alias al='cmd'
You can read more about it over here.

How to check for the presence of a git repository in a directory using bash script

I am trying to work with git on my project.
I want to set up the terminal such that whenever I cd into a directory that contains a git project, the terminal should indicate which git branch I am currently on.
If there is a git project, the terminal show only the name of the branch,
for example
(master) $
otherwise it should show the current directory path.i.e
username#machinename:path/to/directory $
I found a similar question answered here but i don't know how to modify the answer to suit my need, because am not good with bash scripting.
Any suggestion will be highly appreciated.
Have a look at this project https://github.com/jimeh/git-aware-prompt, it should solve your whole problem and when not, you can change it to meet your needs. Main logic is in prompt.sh.
To find current git branch name in directory, you can always run
git rev-parse --abbrev-ref HEAD
It will return branch name, HEAD (when detached) or nothing when directory is not par of git repository. If you need only this information, you can update your .bashrc. Edit variable PS1, which is bash prompt format.
PS1='(`git rev-parse --abbrev-ref HEAD 2> /dev/null`) \$ '
This is example how to display branch name anywhere in the prompt. The git script will help you and recognize whether to show branch or directory. It will update your PROMPT_COMMAND, which is called every time the bash prompt line is displayed, by checking for git branch name which you can then use in PS1 as a variable. You can then update your existing PS1='${debian_chroot:+($debian_chroot)}\u#\h:\w\$ ' to
PS1='${debian_chroot:+($debian_chroot)}\u#\h:\w \(\$git_branch\)\$ '
You have many tools which do it.
myzsh for example or just a simplt bash that you add to your bashrc
http://martinvalasek.com/blog/current-git-branch-name-in-command-prompt
example:
function parse_git_branch () {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
RED="\[\033[0;31m\]"
YELLOW="\[\033[0;33m\]"
GREEN="\[\033[0;32m\]"
NO_COLOR="\[\033[0m\]"
PS1="$GREEN\u#\h$NO_COLOR:\w$YELLOW\$(parse_git_branch)$NO_COLOR\$ "
The Git package in Linux usually comes with a prompt script that you can use to see the repository status. To enable it, source the git-prompt.sh script in a shell startup file (e.g. ~/.bashrc), then set a custom prompt with the %s parameter. For example, in ArchLinux you could do:
[ -r /usr/share/git/completion/git-prompt.sh ] && . /usr/share/git/completion/git-prompt.sh
PS1='[\u#\h \W$(__git_ps1 " (%s)")]\$ '
When changing to a directory of a Git repository, the prompt will change to show the branch name. Extra details can be set to be shown by the prompt (see the link above).

How to track changes of my Linux distrib with git?

I am experimenting some linux configuration and I want to track my changes? Of course I don't want to to put my whole OS under version control?
Is there a way (with git, mercurial or any VCS) to track the change without storing the whole OS?
This is what I imagine:
I do a kind of git init -> all hashes of all files are stored, but not the content of the files
I make some changes to my file system -> git detect that the hash of this file has changed
I commit -> the content of the file is stored (or even better the original file and the diff are stored! I know, that is impossible... )
Possible? Impossible? Work-arounds?
EDIT: What I care about is just to minimize the size of the repository and to have a repository containing only my changes. Having all files in my repository is not relevant for me. For example if i push to github I just want it to contain only the files that has changed.
Take a look at etckeeper, it will probably do the job.
What you want is git update-index --info-only or ... --index-info, from the man page: " --info-only is used to register files without placing them in the object database. This is useful for status-only repositories.". --index-info is its industrial-scale cousin.
Do that with the files you want to track, write-tree to write the index structure into the object db, commit-tree that, and update-ref to update a branch.
To get the object name use git hash-objectfilename.
Here is what we do...
su -
cd /etc
echo "*.cache" > .gitignore
git init
chmod 700 .git
cd /etc; git add . && git add -u && git commit -m "Daily Commit"
Then setup crontab:
su -
crontab -e
# Put the following in:
0 3 * * * cd /etc; git add . && git add -u && git commit -m "Daily Commit"
Now you will have a nightly commit of all changes in /etc
If you want to track more than /etc in one repo, then you could simply do it at the root of your filesystem, except add the proper ignore paths to your /.gitignore. I am unclear on the effects of having git within git, so you might want to be extra careful in that case.
I know this question is old, but I thought this might help someone. Inspired by #Jonathon's comment on the How to record concrete modification of specific files question, I have created a shell script that enables you to monitors all the changes done on a specific file, while keeping all the changes history. the script depends on the inotifywait and git packages being installed.
You can find the script here
https://github.com/hisham-hassan/linux-file-monitor
Usage: file-monitor.sh [-f|--file] <absolute-file-path> [-m|--monitor|-h|--history]
file-monitor.sh --help
-f,--file <absolute-file-path> Adding a file to the monitored files List. The <absolute-file-path>
is the absolute file path of the file we need to action.
PLEASE NOTE: Relative file path could cause issues in the script,
please make sure to use the abolute path of the file. also try to
avoid sym links, as it has not been tested.
example: file-monitor.sh -f /absolute/path/to/file/test.txt -m
-m, --monitor Monitoring all the changes on the file. the monitoring will keep
happening as long as the script is running; you may need to run it
in the background.
example: file-monitor.sh -f /absolute/path/to/file/test.txt -m
-h, --history showing the full history of the file.
To exit, press "q"
example: file-monitor.sh -f /absolute/path/to/file/test.txt -h
--uninstall uninstalls the script from the bin direcotry,
and removes the monitoring history.
--install Adds the script to the bin directory, and creates
the directories and files needed for monitoring.
--help Prints this help message.

Symbolic link to a hook in git

I wrote my own custom post-merge hook, now I added a "hooks" directory to my main project folder (since git doesn't track changes in .git/hooks), somewhere I read that I can make a symbolic link from hooks to .git/hooks so I don't have to copy the file from one folder to the other every time someone changes it so I tried:
ln -s -f hooks/post-merge .git/hooks/post-merge
But it doesn't seem to work, any ideas why? "ln hooks/post-merge .git/hooks/post-merge" works fine but making a hard link is the same as copyin I guess....
you just used wrong path, it should be:
ln -s -f ../../hooks/post-merge .git/hooks/post-merge
While you can use symbolic links, you can also change the hooks folder for your project in your git settings with :
git config core.hooksPath hooks/
Which is local by default so it won't ruin git hooks for your other projects. It works for all hook in this repository, so it's especially useful if you have more than one hook.
If you already have custom hooks in .git/hooks/ that you do not want to share with your team you can add them in hooks/ and add a .gitignore so they're not shared.
Changing directory before linking
cd /path/to/project-repo/.git/hooks
ln -s -f ../../hooks/post-merge ./post-merge
The path calculation is done relative to the symlink. Let's understand using an example,
ln -s path/to/file symlink/file
Here, the path to the file should actually be the relative path from the symlink path.
The system actually calculates the file path as symlink/path/path/to/file
The above command should be re-written as
ln -s ../path/to/file symlink/path
The folder structure being,
/code
------ symlink/file
------ path/to/file
Utilizing Michael Cihar's comment, here is an example of a bash script I wrote to simply create these symlinks. This script is located in git_hooks/ dir which is at the project root. My .git/ folder is also in the same directory level.
#!/usr/bin/env bash
pwd=$(pwd);
# Script is designed to be ran from git_hooks/ dir
if [[ "$pwd" == *"git_hooks"* ]]; then
files=$(ls | grep -v -e '.*\.');
while read -r file; do
ln -s ../../git_hooks/$file ../.git/hooks/
echo "Linked $file -> ../.git/hooks/$file"
done <<< "$files";
else
echo "";
echo "ERROR: ";
echo "You must be within the git_hooks/ dir to run this command";
exit 1;
fi
My script must be ran from within the actual git_hooks/ directory. You can modify it to behave differently, if you'd like.
This script will symlink any file that is not suffixed with a file extension within the git_hooks/ directory. I have a README.txt in this directory + this script (named symlink.sh). All the actual git hooks are named 'pre-commit', 'pre-push', etc. so they will be symlinked.
why not just
cp ./hooks/* .git/hooks/
this worked for me in Mac OS

Resources