《Git In Practice》 Notes

Some advance git operations and examples.

Remote Operation

  1. The command git remote prune <git-repo-path> deletes any remote references to branches that have been deleted from the remote repository by other users. See more about this .

  2. Please be very careful when you run command git push --forced, it’s very dangerous because it will rewrite all you related histories in the remote side.

  3. When you want to clone a very large repository in a very short time, you can use command like git clone --depth 1 and option name depth indicate specific versions/levels and in this case it will only clone the latest version.

  4. Transfer repository through different manage physical repository:

  • Use command git clone --mirror git@bitbucket.org:<user-name>/<repo-name>
  • Use command git remote set-url --push git@github.com:<user-name>/<repo-name>
  • Use command git push --mirror to finish process.

Diff Operation

  1. You can use command git diff --staged to check the differences between the staged file and file in the HEAD and append parameter --word-diff can show modifications per word.

git-diff-staged-word-diff

  1. Remember to setup the merge tool so that no need to install the software like source tree. For me, I use tool name icdiff.

icdiff-screenshot

Tag Operation

  1. You can use git tag <tag-name> to make a label for specific commit. If you want to update the software, just release a new one. A tag is another ref for a single commit. Tags differ from branches in that they’re usually permanent, so don’t change the label later and also use option --force can make an existing tag direct to a new commit.

git-tag-name

  1. By the way, if you want to push tags, you should use git push -tags. If you have to change tags that already been pushed to the remote, you can use git push --tags --force, but creating a new tag and pushing that new one is recommended since it will have no bad effect on other people.

Useful Skills and Knowledges

  1. You can use command git show-ref --tags to see all tags and git show-ref --heads to see all branches.

git-show-ref

  1. Inside command git pull are actually two other commands git fetch and git merge.

  2. If you are not for sure when running some delete or any other dangerous commands, please use the --dry-run option if it’s existed.

git-rm-dry-run

  1. You can use the -- option between ref and file paths to avoid “strange” name.

git-illegal-name

  1. You can also use command tool rev-parse to see what a given ref expands to, but usually a four-character string is unique enough to identify the specific commit.

git-rev-parse

  1. We can use git shortlog to see who contributes most.

git-shortlog

  1. You can enable git rerere to automatically resolve these same conflicts and use git rerere forget *** to ignore some previous wrong conflict fix.

git-rerere

  1. You can use command git describe --tags to generate version number and the format is <latest-tag>-<commit-amount-to-the-latest-tag>-<latest-commit-SHA-1>.

git-describe-tags

  1. Command git reflog record every action that affect the HEAD pointer and actually, it is an alias for git log --walk-reflogs --abbrev-commit --pretty=oneline and it only reflect those changes which happened in local machine. Command git reflog expire --expire=now --all can clear all existed reflog and generally, we just use command git reflog expire --expire-unreachable=now --all so that the operation will only apply to those unreachable ref logs.

  2. You can use git cherry --verbose <branch-ref> to see which commits have not yet been merged or pushed to the remote. It will compare the current branch with the branch you dictate in the parameter, the default value which can be ignored is the remote branch.

  3. Always remember to differentiate author with committer and use git blame <file-path> to see editor’s information about every line of the file even you rename the file itself.

git-blame-file

  1. You should use command git fsck to verify the integrity of the repository after you hit some hard disk problem which may hurt the current local git database (.git folder).

  2. Appending --web option to the git help <command> can show help file in HTML version in the browser.

Branch Operation

  1. An advice to naming the new branch: using multiple words separated by hyphens like fix-feature-a.

  2. A --merges or --min-parents=2 flag used by git log will only show merge commits and if you do want every merge processes have a separated commit, you should use no-ff option when you merge branches.

  • With --no-ff option:

git-merge-no-ff

  • Default:

git-merge-ff

  1. Choose appropriate strategy to merge the branch like git merge --strategy=recursive and you can also use the --strategy option to transfer some options.

  2. Using git checkout -b <branch-name> to create a new branch base on current branch and append based-on-ref option can give you more precise control.

Local Operation

  1. Mostly, git will recognize file’s rename and movement and if it doesn’t, you should use git mv <file-path> to do that. Remember, git doesn’t handle moving files between different repositories and it only take care of its own repository.

  2. If you really need to neglect some specific files, please put those rules in the .gitignore file and meanwhile, you should avoid use command git add --force <file-path> to add ignored file. Another way is using git update-index --assume-unchanged to ignore some specific files so that git will no longer check those files and you can use git ls-files -v to see all the files including those ignored files. By the way, if you want to re-check those files, you can run git update -index --no-assume-unchanged to those files.

  3. git reset --mixed only undoes files added by command git add like command git checkout --force but command git reset --hard undoes all file modifications including files added by git add The default reset algorithm for this command is mixed. In short, remember hard option resets the index and the working directory, and mixed option resets the index but not the working directory.

  4. The command git clean -X will only remove ignored files from the working directory but option -x will remove not-only those ignored files but all the untracked files like using command git clean --force

git-clean-x

  1. Recommand using command git clean -i intuitivilty to remove files.

git-clean-i

  1. If you want to keep the top stack stash, you can use git stash apply instead of git stash pop.

  2. The command git bisect is very useful to find which commit may have a regression bug and you can provide a test script which has defined output so that the git will automatically run this script on each commits so that you can identify which commit has broken.

  • Use command git bisect start.
  • Use command git bisect good|bad to label the commit.
  • Git will find the first bad commit.
  • Use command git bisect reset to stop.

git-bisect-demo

  1. Command git commit --amend can rewrite the latest commit’s message. Inside this process, there are two operation.

  2. Often git clean -xdf is run after git reset --hard to make sure the repository is clean.

  3. You can use git log --format=email to decide whether the commit content is good or not and you can also to write your own format style for other purposes which means when you are writing the commit message, you should use the way to write the email. For example, the commit should have “subject” and “content”.

  4. You can use git pull --rebase to replace git pull and it will make the history look more flatten by avoiding a single new merge commit.

  5. You can use git filter-branch <command> to do some entire history for repository. For example, you can rewrite author info totally.

Rewrite History

  1. When you use function name cherry-pick, remember to use --edit option to add some commit message or use --signoff to clearly indicate who do that. If you hit merge conflict, please use git cherry-pick --continue or git cherry-pick --abort to submit or ignore this change and the “continue, abort” pattern are also appropriate to rebase.

  2. You can use git revert <commit> to undo one specific commit and also remember to use --signoff option, but this is quite different than rebase which will change the history instead of appending a new one.

git-revert

  1. At first, git will run command git reset --soft HEAD^.
  • Before:

git-reset-soft-before

  • After:

git-reset-soft-after

  • Restore:

git-reset-soft-restore

Then, it will run command git commit --reedit-message and open the editor for you to change the message.

Notice: This will rewrite the history and need --force option to push changes to the remote.

  1. By the way, git reset --soft *** will rests neither the staging area nor the working tree but just changes the HEAD pointer to point to the previous commit.

Personalize Git

  1. Remember, when using command git log <location> <section>.<key> <value> to write value, you can point out which one you want to change.
  • --global option will use the file in your $HOME directory.
  • --system option will use the file alongside with the folder in which Git was installed.
  • --local option will use the file alongside with current repository. The default option is this.
  • --file option let you to provide the file path.

Priority list: --file > --local > --global > --system.

By the way, Git sets values in a branch section in the --local position so that it will know how to pull or merge the code.

git-local-config-branch-set

  1. By default, when you execute command git push, Git will push all related branchs’ changes to the remote. It will accidentally push changes made on other branches. So, you can set the default push strategy to simple.

  2. {#git-remote-prune#} By setting fetch.prune to 1 will trigger the command git remote prune on every git fetch or git pull operation.

  3. Git allows you to set a global ignore file so that you can put your personal ignore rules in it. That is very useful if you are working with other teammates who may have different opinion on ignore rules. Usually, we put our own global ignore file in the $HOME directory and use command git config --global core.excludesfile ~/.gitignore to identify it.

  4. For people who are using Mac OS X can store their password in the keychain which is natuely supported by the Git. The command is git config --global credential.helper oskeychain.

  5. Use git config --global help.autocorrect 1 to let Git fix your wrong spell commands.

git-help-autocorrect

Advice

  1. The main rule to avoid data loss therefore is commit early and commit often. Always try to use make/rewrite commits instead of stash, because cleared stashes can’t be easily recovered.

  2. Never write history on branches which other people may use and remember to pull the source first so that you aren’t rewriting commits on the remote branch that you don’t have locally.

  3. If you just want to create a public repository and put it on the internet, you could use git init --bare repo-name to initialize the repository and in that case, this repo will only allow changes pushed from other repository.

  4. Command git add --patch can allow you stage changes one by one.

git-add-patch

Submodule

  1. Use command git submodule add <repository_address> <local_path> to add submodule. Git’s submodules store the the reference to a specific SHA-1 reference in another remote Git repository and store these in subdirectories of the current repository.

git-add-submodule

git-submodule-info

By the way, it also provide --depth option like git clone.

  1. Use command git submodule init to initialize all submodules which will copies all the submodule names and URLs from the .gitmodules file to the local repository Git configuration file so that when you run git pull, Git will knows to pull the latest changes for submodules.

git-submodule-local-info

  1. Use command git submodule update to update the stored submodule revision to the latest revision in the local. It also provide you two useful options: --recursive and --init. The first option is useful when there are nested submodules inside submodules. The second option can help you to avoid run git submodule init. This command also provides --depth option.

Please testing the changes made to the submodule remain compatible with the main project.

  1. When you try to entirely clean up submodules, please remember to delete folder name .git/modules too. Because Git will initially cloned submodules to this folder and then copy that to the path that you indicated.

  2. git submodule foreach <command> is very useful for you to run command on all submodules and with option --recursive, it can touch all submodules. The command can access to below variables: $name, $path, $sha1 and $toplevel.

git-submodule-command


  1. This book is now open source and host in here .
  2. Some useful articles published by ATLASSIAN .
updatedupdated2023-12-052023-12-05