Working with Git
Basic Git Commands and Workflow
Initializing a Repository
To start using Git, you need to initialize a repository in your project directory. This creates a .git
directory that tracks all changes.
git init
Checking the Status of Your Repository
Use git status
to see the state of your working directory and staging area. It shows which changes have been staged, which haven’t, and which files aren’t being tracked by Git.
git status
Adding Files to the Staging Area
Before committing changes, you need to add them to the staging area using git add
. This prepares the files to be included in the next commit.
git add <filename>
To add all changes in the directory:
git add .
Committing Changes
After staging the files, commit them to the repository with a message describing the changes.
git commit -m "Your commit message"
Git Workflow
The image above illustrates the Git workflow1. It starts with modifying files in your working directory. Once changes are made, you add them to the staging area using git add
. After staging, you commit the changes to the repository with git commit
. This cycle repeats as you work on your project.
Pushing Changes to a Remote Repository
To share your changes with others, push them to a remote repository like GitHub.
git push origin main
Creating a New Repository
Create a new Git repository in a new directory and add a file to it. Stage and commit the changes.
Solution
-
Create a new directory and navigate to it:
mkdir myproject cd myproject
-
Initialize a Git repository:
git init
-
Add a new file and commit it:
echo "Hello, Git!" > hello.txt git add hello.txt git commit -m "Add hello.txt"
Note
Keep in mind that Git local repository is a hidden directory .git
in the root of your project directory. It contains all the necessary metadata for version control. If you delete this directory, you will lose your project history as well. To serve as a backup, you can push your changes to a remote repository.
Create repository on GitHub
Create a new repository on GitHub and connect it to your local repository. Push your changes to the remote repository.
Solution
-
Create a new repository on GitHub. Do not initialize it with a README, .gitignore, or license.
-
Connect your local repository to the remote repository:
# substitute your username and repository name git remote add origin https://github.com/yourusername/your-repository.git
-
Push your changes to the remote repository:
git push -u origin main
Branching and Merging
Working with Branches
Branches are an essential part of Git, allowing you to work on different features or fixes independently. This helps in maintaining a clean and organized project history.
Creating a Branch
To create a new branch, use the git branch command followed by the branch name:
git branch <branch-name>
Switch to the new branch using git checkout:
git checkout <branch-name>
Or, you can create and switch to a new branch in one command:
git checkout -b <branch-name>
Why Use Branches?
- Isolation: Keep different lines of development separate.
- Collaboration: Multiple team members can work on different features simultaneously.
- Experimentation: Safely try out new ideas without affecting the main codebase.
- History: Each branch maintains its own history of commits, making it easy to track changes and revert if necessary.
- Merging: Once the work on a branch is complete, it can be merged back into the main branch, integrating the changes.
Merging a Branch
First, switch to the branch you want to merge into:
git checkout main
Then, merge the feature branch:
git merge <branch-name>
Best Practices for Merging
- Regularly Sync with Main: Frequently merge changes from the main branch into your feature branch to minimize conflicts.
- Use Pull Requests: For collaborative projects, use pull requests to review and discuss changes before merging.
- Resolve Conflicts Carefully: If conflicts arise, carefully resolve them to ensure the codebase remains stable.
Handling Merge Conflicts
Merge conflicts occur when changes in different branches conflict with each other. Git will mark the conflicts in the affected files, and you will need to resolve them manually.
Steps to Resolve Conflicts
1. Identify Conflicts: Git will highlight the conflicting areas in the files.
2. Edit Files: Manually edit the files to resolve conflicts.
3. Stage Resolved Files: Once resolved, stage the files using git add.
4. Complete the Merge: Commit the merge to complete the process.
git add <resolved-file> git commit
By following these practices, you can effectively manage branches and merges in your Git workflow, ensuring a smooth and efficient development process.
Creating and Merging Branches
Create a new branch, make changes, and merge it back into the main branch.
Solution
-
Create a new branch and switch to it:
git checkout -b feature-branch
-
Make changes to your files and commit them:
git add . git commit -m "Add new feature"
-
Switch back to the main branch and merge the feature branch:
git checkout main git merge feature-branch
Resolving Merge Conflicts
Using VS Code, clone the playgound repository and follow instructions to create a merge conflict and resolve it.
Solution
git clone git@github.com:ELIXIREstonia/2024-11-06-git-playground.git
git checkout ugly-conflict # this is needed to fetch the branch from origin
# make changes to the README.md file if you feel like it
git add README.md
git commit -m "Change README.md"
git checkout main
git merge ugly-conflict
# resolve the conflict in the README.md file (VS Code will help you)
git add <resolved-file>
git commit
Navigating Git History
Exploring Git Logs and History
Understanding the history of your project is crucial for tracking changes, debugging issues, and collaborating with others. Git provides several commands to help you navigate and manage your project’s history.
Viewing Commit History
The git log
command displays the commit history of your repository.
git log
This command shows a list of commits, including the commit hash, author, date, and commit message. You can use various options to customize the output:
--oneline
: Show each commit on a single line.--graph
: Display a graphical representation of the commit history.--decorate
: Show branch and tag names alongside commit messages.
git log --oneline --graph --decorate
Reverting Changes
If you need to undo changes, Git provides several options:
Reverting a Commit
The git revert
command creates a new commit that undoes the changes from a previous commit.
git revert <commit-hash>
Resetting to a Previous Commit
The git reset command moves the current branch to a specified commit. This can be used to undo commits or unstage changes.
--soft
: Keep changes in the working directory and staging area.--mixed
: Keep changes in the working directory but unstage them.--hard
: Discard all changes and reset the working directory to the specified commit.
git reset --hard <commit-hash>
Note
Be cautious when using git reset --hard
, as it permanently removes changes and cannot be undone. Almost always a better option is to use git revert
, especially if changes have been pushed to a (collaborative) remote repository.
Collaborating with Remote Repositories
Collaboration and Remote Workflows
Collaborating with others on a project often involves using remote repositories. These repositories, hosted on platforms like GitHub, GitLab, or Bitbucket, allow multiple contributors to work on the same codebase.
Setting Up a Remote Repository
To start collaborating, you need to set up a remote repository and connect your local repository to it.
Adding a Remote Repository
Use the git remote add
command to add a remote repository. Replace
git remote add origin <remote-url>
Verifying Remote Repositories
To verify that the remote repository has been added, use the git remote -v
command.
git remote -v
Pushing Changes to a Remote Repository
After committing your changes locally, you can push them to the remote repository to share with others.
git push origin main
Pulling Changes from a Remote Repository
To update your local repository with changes from the remote repository, use the git pull
command.
git pull origin main
Creating and Managing Pull Requests
Pull requests (PRs) are a way to propose changes to a repository. They allow team members to review and discuss changes before merging them into the main branch.
Note
You can clone all public repositories without authentication. However, to push changes to a repository, you need to authenticate with the remote platform. Also you can’t push to a repository you don’t have write access to (you are not part of the team – collaborators). Most open source projects are such public repositories and you can
1. fork them to your own account and push changes to your fork.
2. then create a pull request to the original repository.
Creating a Pull Request
- Push Your Branch: Push your feature branch to the remote repository.
git push origin <branch-name>
- Open a Pull Request: On the remote repository platform (e.g., GitHub), navigate to the repository and open a new pull request from your feature branch to the main branch.
Reviewing and Merging Pull Requests
Team members can review the pull request, leave comments, and suggest changes. Once the changes are approved, the pull request can be merged into the main branch.
Best Practices for Teamwork
- Branch Naming Conventions: Use clear and consistent naming conventions for branches (e.g.,
feature/
,bugfix/
,hotfix/
). - Code Reviews: Conduct thorough code reviews to maintain code quality and share knowledge.
- Frequent Commits: Commit changes frequently with meaningful commit messages.
- Sync Regularly: Regularly pull changes from the remote repository to stay up-to-date with the latest codebase.
- Resolve Conflicts Early: Address merge conflicts as soon as they arise to avoid larger issues later.
Creating a pull request
Create a new branch, make changes, push the branch to the remote repository, and create a pull request. You can use the playground repository to practice.
Handling Common Issues
Tips for Managing Git Challenges
Handling merge conflicts, using .gitignore, and maintaining a clean Git history.
Handling Merge Conflicts
Merge conflicts occur when changes in different branches conflict with each other. Git will mark the conflicts in the affected files, and you will need to resolve them manually.
Steps to Resolve Conflicts
1. Identify Conflicts: Git will highlight the conflicting areas in the files.
2. Edit Files: Manually edit the files to resolve conflicts.
3. Stage Resolved Files: Once resolved, stage the files using git add.
4. Complete the Merge: Commit the merge to complete the process.
git add <resolved-file>
git commit
Using .gitignore
The .gitignore file specifies which files and directories to ignore in a project. This is useful for excluding temporary files, build artifacts, and other files that should not be tracked by Git.
Creating a .gitignore File
Create a .gitignore file in the root of your repository and add patterns for files and directories to ignore.
# Example .gitignore file
*.log
*.tmp
node_modules/
dist/
Maintaining a Clean Git History
A clean Git history makes it easier to understand the evolution of a project and track down issues. Here are some tips for maintaining a clean history:
- Frequent Commits: Commit changes frequently with meaningful commit messages.
- Squash Commits: Squash multiple related commits into a single commit before merging.
Wrap-Up and Best Practices
Summary of key points, practical tips for effective use of Git, and a Q&A section for participants.
Key Points
- Version Control: Git is a powerful version control system that helps you track changes, collaborate with others, and manage your project’s history.
- Basic Commands: Familiarize yourself with basic Git commands like
git init
,git add
,git commit
,git status
,git push
, andgit pull
. - Branching and Merging: Use branches to work on different features or fixes independently, and merge them back into the main branch when ready.
- Collaboration: Use remote repositories and pull requests to collaborate with others and review changes before merging.
Practical Tips
- Commit: Make commits with clear semantic messages.
- Use Branches: Create branches for new features, bug fixes, and experiments.
- Sync Regularly: Pull changes from the remote repository frequently to stay up-to-date.
- Resolve Conflicts Early: Address merge conflicts as soon as they arise to avoid larger issues later.
- Review Code: Conduct thorough code reviews to maintain code quality and share knowledge.
-
Scott Chacon and Ben Straub. Pro Git. Apress, 2014. URL: https://git-scm.com/book/en/v2. ↩