This covers tips and tricks across git & github repository.
git needs to authenticate with enterprise and external repos. This section covers some of those tips and tricks.
Git typically uses a simple key or user id & password for authenticating users. In case the authentication involves more complex authentication flows (like OAuth & other complext MFA use-cases at Team Studio, Bitbucket & github), a custom credential manager can be plugged in. A popular one is from Microsoft called Git Credential Manager for Windows and Git Credential Manager for Mac & Linux.
By design the credential manager caches the credential. But in case the credential has changed or invalid credential was provided (including cancelling the popup), the credential must be cleared.
$ git credential-manager clear
Target Url:
https://<github server>/path/to/project.git
In some cases, git repository may be setup such that it either requires mutually authenticated SSL or supports mutually authenticated SSL as first step and if that fails switches to SAML/OpenID Connect/OAuth authentication (this allows support for both SSO for web and mutual auth SSL for command line tools). In such scenario, it is important for the tools to support mutually authenticated SSL. The client certificate for mutually authenticated SSL may exist as a file or in a corporate world may be stored in appropriate repository on device (Mac - Keychain, Windows - Cert store).
On windows, this is achieved by using Windows SSL libraries (typically an option while installing the Git for Windows client version 2.14 and later). You can confirm whether the git is using the correct SSL libraries by executing the following command
$ git config --get http.sslbackend
schannel
In case the value above is openssl
, change the value as follows
git config --global http.sslBackend schannel
Note : The --global
will change setting for all the git repositories on the machine. If you want to limit change to your repository, try using --local
.
git on Mac supports certificate files for authentication. But there is no official support for keychain. In worst case scenario, you can use a specific version of git (from brew) that integrates with curl that can integrate with Keychain and use the certificate stored in keychain.
- Install curl
$ brew install curl
- Install git
$ brew install --with-curl https://raw.githubusercontent.com/Homebrew/homebrew-core/a86ae8fc2b24001b3c6460a46dbfc6e323d2a4d1/Formula/git.rb
- Check installed git
$ /usr/local/bin/git --version
- Check keychain for any website specific Internet password already stored (for example if git location is https://example.com/project1/project1.git, the keychain may have an internet password stored against https://example.com). If so, delete the same otherwise the tool is going to use that without prompting for new password.
- Execute the command as follows to clone the repository. In case there is no existing password in the keychain, the system will prompt user for user id & password and then complete the execution.
$ /usr/local/bin/git clone https://example.com/project1/project1.git
Tips and tricks to manage your git repository
git for-each-ref --format='%(committerdate) %09 %(authorname) %09 %(refname)' | sort
git remote update origin --prune
There are multiple scenarios in which conflict can happen. This section provides some of the approaches that should be used.
original_branch: A – B – F
\
new_branch: C – D – E <-- rebase
In case the original branch has been updated after the initial branch, depending on the changes, conflict may arise in case of rebase before merging to original branch. In such a scenario the following steps can be followed.
- Start the rebase by specifying the original branch
git checkout new_branch; git rebase original_branch
. This should display all the files that is resulting in conflictgit rebase dev First, rewinding head to replay your work on top of it... Applying: Commit comment .git/rebase-apply/patch:134: trailing whitespace. warning: 1 line adds whitespace errors. error: Failed to merge in the changes. Using index info to reconstruct a base tree... M folder1/folder2/file1.txt Falling back to patching base and 3-way merge... Auto-merging folder1/folder2/file1.txt CONFLICT (content): Merge conflict in folder1/folder2/file1.txt <---------------------------- Patch failed at 0001 Commit comment. The copy of the patch that failed is found in: .git/rebase-apply/patch Resolve all conflicts manually, mark them as resolved with "git add/rm <conflicted_files>", then run "git rebase --continue". You can instead skip this commit: run "git rebase --skip". To abort and get back to the state before "git rebase", run "git rebase --abort".
- Run through the following steps for each of the file identified with conflict
- Fix the conflict i.e. find the area in file that has
<<<<<<<
and>>>>>>>
and fix the content between the two and remove all the line that contain added content like<<<<<<<
,>>>>>>>
&=======
. - Add the updated file explicitly using
git add <conflict file>
to ensure that git understands you have fixed conflict
- Fix the conflict i.e. find the area in file that has
- Run
git rebase --continue
to continue the rebasing process. In case additional conflicts are flagged, execute step 2 to fix the changes - At this time pull the branch and identify the conflict files.
$ git pull Auto-merging folder1/folder2/file1.txt CONFLICT (content): Merge conflict in folder1/folder2/file1.txt Automatic merge failed; fix conflicts and then commit the result.
- Fix the conflicts identified and run
git add <conflict file>
- Commit the changes
git commit -m 'comment'
and push the updategit push
git clone git@github.com:MicrosoftDocs/azure-docs.git --branch master --single-branch --depth 1
Use the date which is 1 day before last update (can be figured out by using git log HEAD origin/master
to identify when )
git fetch --shallow-since="2021-11-21"
git merge
Git updates on a daily basis can ensure that all the changes being made are against the latest version of the code. Keeping that in mind, this script runs pull on ALL the git repos at the given location. This script is written for zsh and may need change to run in bash or other shell.
export DEFAULT_GIT_REPO_LOCATIONS=('/Users/jhash/Projects')
updateGit() {
local repoLocations=($@)
if [[ ${#repoLocations} -eq 0 ]]; then
repoLocations=(${DEFAULT_GIT_REPO_LOCATIONS})
fi
local repoLocation
local gitDirs
local gitDir
local gitErr
for repoLocation in $repoLocations;
do
echo "Processing location ${repoLocation}"
gitDirs=("${(@f)$(find ${repoLocation} -name '.git' -exec dirname {} \; )}")
for gitDir in $gitDirs
do
echo "************** Updating ${gitDir} **************"
gitout=$(git -C "${gitDir}" pull)
gitErr=$?
if [[ $gitErr -ne 0 ]]; then
echo "${gitout}"
echo "XXXXXXXXXXXXXX Updating ${gitDir} XXXXXXXXXXXXXX"
else
echo "************** Updated ${gitDir} **************"
fi
done
done
echo "Updated repos"
}
Tips and tricks for github repo. Most of the following can be run for enterprise repo by setting GH_HOST=<domain e.g. github.xyz.com>
environment variables
Github allows user to fork repos but once forked, it is responsibility of the fork owner to keep it synced with upstream repo. Not being diligent can result in merging issues later due to significant fallback in forked repo state. This scripts identifies all the forked repos of the user and syncs them with upstream system using gh
CLI
# Run the following line if you want to work on Github enterprise
# export GH_HOST=github.xxx.yyy.com
updateRepos() {
echo "Checking login..."
gh auth status
alreadyLogin=$?
if [[ "${alreadyLogin}" -eq "1" ]]; then
echo "Please complete login using 'gh auth login' before running the script again"
exit 1
fi
listOfRepos=$(gh repo list --fork --json owner,name | jq -r '.[]|.owner.login+"/"+.name')
repos=("${(f)listOfRepos}")
for aRepo in $repos
do
echo "Processing repo $aRepo"
listOfbranches=$(gh api "repos/$aRepo/branches" | jq -r ".[]|.name")
branches=("${(f)listOfbranches}")
for aBranch in $branches
do
echo "Processing repo $aRepo and branch $aBranch"
gh repo sync "${aRepo}" -b "${aBranch}"
done
done
}