Git Operations Guide

Introduction

Git is a version control system and a powerful tool for tracking the change history of software development projects. This page explains Git operational methods and integration with CI/CD tools.

Table of Contents

Git Flow

Git Flow is one of the methodologies for branch management using Git, proposed by Vincent Driessen in 2010. This workflow provides a systematic approach to efficiently advance development while maintaining code quality, especially in large-scale projects where multiple developers work simultaneously.

Git Flow uses multiple branches with specific roles, each representing different stages of the development process. This model enables organized release management, feature development, and bug fixes.

Main Branches in Git Flow

Main Branches

In Git Flow, there are always two main branches:

master (main) branch

This branch contains production-ready code. The code in this branch should always be in a deployable state for the production environment. Commits to the master branch are typically made only during new version releases or when applying hotfixes.

develop branch

This branch reflects the latest state of development. Development work for the next release branches off from this branch, and completed features are merged back into it. When the develop branch is stable and ready for release, a release branch is created to prepare for the release.

Supporting Branches

Git Flow uses the following three types of supporting branches:

feature branches

These branches are used for developing new features. They always branch off from the develop branch and are merged back into the develop branch when development is complete. The naming convention is typically feature/feature-name.

Creation method: git checkout -b feature/new-feature develop

Merge method: git checkout developgit merge --no-ff feature/new-feature

release branches

These branches are for release preparation. They branch off from the develop branch, and when release preparation is complete, they are merged into both master and develop. Only bug fixes and small changes related to the release are made on this branch; no new features are added. The naming convention is typically release/version-number.

Creation method: git checkout -b release/1.0.0 develop

Merge method:

git checkout mastergit merge --no-ff release/1.0.0git tag -a 1.0.0

git checkout developgit merge --no-ff release/1.0.0

hotfix branches

These branches are used for urgent bug fixes discovered in the production environment. They branch off from the master branch, and after the fix is complete, they are merged into both master and develop. The naming convention is typically hotfix/version-number.

Creation method: git checkout -b hotfix/1.0.1 master

Merge method:

git checkout mastergit merge --no-ff hotfix/1.0.1git tag -a 1.0.1

git checkout developgit merge --no-ff hotfix/1.0.1

Git Flow Implementation Methods

git-flow Tool

There is a command-line tool called "git-flow" for implementing Git Flow. Using this tool makes it easy to perform branch operations according to the Git Flow workflow.

Installation Methods

macOS (Homebrew): brew install git-flow-avh

Ubuntu/Debian: apt-get install git-flow

Windows (Git for Windows): Included by default

Basic Usage

Repository initialization: git flow init

Start feature development: git flow feature start feature-name

Complete feature development: git flow feature finish feature-name

Start release preparation: git flow release start version-number

Complete release preparation: git flow release finish version-number

Start hotfix: git flow hotfix start version-number

Complete hotfix: git flow hotfix finish version-number

Advantages and Disadvantages of Git Flow

Advantages

  • Clearly defined branch structure makes it easier to organize development in large teams
  • Facilitates parallel development, allowing multiple features to be developed simultaneously
  • Systematizes the release process, making version management easier
  • Production code (master) is always maintained in a stable state
  • Clearly defined process for urgent bug fixes (hotfixes)

Disadvantages

  • May be too complex for small projects or projects with frequent deployments
  • The number of branches can increase, potentially making management cumbersome
  • May not be suitable for projects practicing continuous delivery (CD)
  • Long-lived branches (especially release branches) are more prone to merge conflicts

Alternative Workflows

GitHub Flow

GitHub Flow is a simpler workflow than Git Flow and is based on continuous deployment. It is characterized by a simple flow of creating feature branches from the master branch and merging them back into master through pull requests after development is complete.

GitLab Flow

GitLab Flow is a workflow positioned between Git Flow and GitHub Flow. It introduces environment branches (production, staging, pre-production, etc.), and is characterized by a gradual merging flow from feature branches to master, and then to environment branches.

Trunk Based Development

Trunk Based Development is a simple workflow where all developers either commit directly to a single branch (trunk/master) or use short-lived feature branches. It is suitable for teams that emphasize continuous integration (CI).

Summary

Git Flow is a branch management strategy particularly suited for large-scale projects or projects with clear release cycles. However, it is not suitable for all projects, and it is important to select an appropriate Git workflow based on the size and requirements of your project.

When adopting Git Flow, the key to success is for the entire team to understand and consistently apply its rules and procedures. Additionally, using the git-flow tool can simplify complex branch operations.

CircleCI

CircleCI is a cloud-based platform for implementing continuous integration/continuous delivery (CI/CD). It integrates with Git repositories such as GitHub and Bitbucket, automatically performing builds, tests, and deployments whenever code changes occur.

By using CircleCI, development teams can automate manual testing and deployment tasks, streamlining the software development process. It also enables early detection of issues, allowing for continuous delivery of high-quality code.

Main Features of CircleCI

Cloud-based CI/CD Platform

CircleCI is a cloud-based service, eliminating the need for infrastructure management. It also offers self-hosted runners, enabling job execution in private environments.

Integration with GitHub and Bitbucket

CircleCI easily integrates with major Git repository hosting services such as GitHub and Bitbucket. It automatically executes workflows triggered by events like pushes to repositories or pull requests.

Parallel Execution and Caching

By running tests in parallel, CircleCI reduces build and test times. It also accelerates repetitive processes by caching dependencies and build results.

Rich Integrations

CircleCI can integrate with many third-party services including Slack, JIRA, AWS, Google Cloud, and Docker. This allows you to integrate development workflows into your existing toolchain.

Flexible Configuration

Using YAML-based configuration files, you can customize build, test, and deployment processes. Complex workflows and conditional executions can also be configured.

Basic Usage of CircleCI

Account Creation and Integration

1. Access the CircleCI website (https://circleci.com/).

2. Sign up with your GitHub or Bitbucket account.

3. Select the repository you want to integrate and click "Set Up Project".

Creating a Configuration File

To use CircleCI, you need to create a .circleci directory in your project's root directory, and place a configuration file called config.yml inside it.

Example of a basic configuration file:

version: 2.1
jobs:
  build:
    docker:
      - image: cimg/node:16.13
    steps:
      - checkout
      - run:
          name: "Install dependencies"
          command: npm install
      - run:
          name: "Run tests"
          command: npm test

Setting Up Workflows

You can set up workflows to run multiple jobs sequentially or in parallel.

version: 2.1
jobs:
  build:
    docker:
      - image: cimg/node:16.13
    steps:
      - checkout
      - run: npm install
      - run: npm run build
      - persist_to_workspace:
          root: .
          paths:
            - .

  test:
    docker:
      - image: cimg/node:16.13
    steps:
      - attach_workspace:
          at: .
      - run: npm test

  deploy:
    docker:
      - image: cimg/node:16.13
    steps:
      - attach_workspace:
          at: .
      - run: npm run deploy

workflows:
  version: 2
  build-test-deploy:
    jobs:
      - build
      - test:
          requires:
            - build
      - deploy:
          requires:
            - test
          filters:
            branches:
              only: main

Key Concepts of CircleCI

Jobs

A job is a unit of work that executes a series of steps (commands). Each job runs in its own execution environment (Executor).

Steps

Steps are individual actions (commands or scripts) that are executed within a job. For example, checking out code, installing dependencies, and running tests are all steps.

Executors

Executors define the environment in which jobs are run. CircleCI provides three types of executors:

  • Docker: Uses Docker images to build the execution environment.
  • Machine: Provides a complete virtual machine environment.
  • macOS: Runs jobs in a macOS environment (used for building iOS apps, etc.).

Workflows

Workflows define the execution order and conditions for multiple jobs. You can run jobs in parallel or execute certain jobs after other specific jobs have completed.

Orbs

Orbs are reusable configuration packages. They allow you to easily incorporate common tasks and integrations into your configuration file. For example, orbs are provided for easy integration with services like AWS, Slack, and Docker.

version: 2.1
orbs:
  node: circleci/node@4.7
  aws-cli: circleci/aws-cli@2.0.3

jobs:
  build-and-deploy:
    executor: node/default
    steps:
      - checkout
      - node/install-packages
      - run: npm run build
      - aws-cli/setup
      - run: aws s3 sync ./build s3://my-bucket/

Advanced Features of CircleCI

Environment Variables and Contexts

Sensitive information (such as API keys and passwords) can be set as environment variables in the CircleCI web interface. Additionally, environment variables that are shared across multiple projects can be managed as "contexts".

Caching and Dependency Management

By caching the results of time-consuming processes, such as installing dependencies, you can reduce build times.

steps:
  - checkout
  - restore_cache:
      keys:
        - v1-dependencies-{{ checksum "package.json" }}
        - v1-dependencies-
  - run: npm install
  - save_cache:
      paths:
        - node_modules
      key: v1-dependencies-{{ checksum "package.json" }}

Parallel Test Execution

By distributing tests across multiple containers for parallel execution, you can reduce testing time.

jobs:
  test:
    parallelism: 4
    steps:
      - checkout
      - run: npm install
      - run:
          command: |
            TESTFILES=$(circleci tests glob "test/**/*.js" | circleci tests split --split-by=timings)
            npm test -- $TESTFILES

Approval Jobs

By adding a manual approval step to a workflow, you can require human approval before executing certain jobs (e.g., deploying to a production environment).

workflows:
  version: 2
  build-test-deploy:
    jobs:
      - build
      - test:
          requires:
            - build
      - hold:
          type: approval
          requires:
            - test
      - deploy:
          requires:
            - hold

CircleCI and Git Integration

Execution Based on Branches and Tags

You can configure jobs to run only for specific branches or tags. For example, you can set up deployments to production to only execute when pushing to the main branch.

workflows:
  version: 2
  build-test-deploy:
    jobs:
      - build
      - test:
          requires:
            - build
      - deploy:
          requires:
            - test
          filters:
            branches:
              only: main
            tags:
              only: /^v.*/

Integration with Pull Requests

CircleCI integrates with pull requests on GitHub and Bitbucket, displaying build results in the pull request status. This makes it easier to check test results during code reviews.

CircleCI Best Practices

Configuration File Validation

Before committing your CircleCI configuration file, it's recommended to validate its syntax using the CircleCI CLI tool.

circleci config validate

Local Test Execution

You can use the CircleCI CLI tool to run jobs locally and test your configuration.

circleci local execute

Build Time Optimization

You can reduce build times using the following methods:

  • Leverage dependency caching
  • Run tests in parallel
  • Design workflows to only execute necessary jobs
  • Use lightweight Docker images

Security Considerations

Sensitive information (API keys, passwords, etc.) should be set as environment variables and not written directly in configuration files. It's also recommended to utilize security-related features such as permission management and audit log review.

Summary

CircleCI is a powerful platform for implementing continuous integration/continuous delivery (CI/CD). By integrating Git repositories with CircleCI, you can automatically build, test, and deploy whenever code changes occur, streamlining the software development process.

By defining flexible workflows using YAML-based configuration files and leveraging parallel execution and caching features, you can improve your development team's productivity. CircleCI also integrates with many third-party services, making it easy to incorporate into existing development workflows.

GitHub Actions

GitHub Actions is a workflow automation tool provided by GitHub. It can automatically execute a series of processes such as building, testing, and deploying, triggered by events that occur in the repository (pushes, pull requests, releases, etc.).

By using GitHub Actions, you can build CI/CD (continuous integration/continuous delivery) pipelines directly within your GitHub repository, eliminating the need for external services. Additionally, you can efficiently construct workflows by reusing numerous actions created by the community.

Main Features of GitHub Actions

Complete Integration with GitHub

GitHub Actions is fully integrated with the GitHub platform. It directly connects with repository code, pull requests, issues, and more, allowing you to seamlessly automate development workflows.

Multi-platform Support

GitHub Actions can run workflows on multiple operating systems including Linux, Windows, and macOS. This makes it easier to build and test applications for different platforms.

Reusable Actions

With GitHub Actions, you can create and share reusable components (actions) for performing specific tasks. The GitHub Marketplace hosts numerous actions created by the community, which you can combine to efficiently build your workflows.

Matrix Builds

GitHub Actions supports matrix builds, which allow you to run jobs in parallel with multiple configurations (different OS or runtime versions, etc.). This enables efficient compatibility testing across different environments.

Self-hosted Runners

In addition to GitHub-provided hosted runners, you can run workflows on your own machines (self-hosted runners). This provides flexibility when you have special hardware requirements or need access to internal networks.

Basic Usage of GitHub Actions

Creating Workflow Files

To use GitHub Actions, you create a YAML file (e.g., ci.yml) in the .github/workflows directory of your repository. This file contains the workflow configuration.

Example of a basic workflow file:

name: CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '16'
        
    - name: Install dependencies
      run: npm install
      
    - name: Run tests
      run: npm test

Key Components of Workflows

GitHub Actions workflows consist of the following key components:

  • name: The name of the workflow
  • on: Events that trigger the workflow (push, pull_request, schedule, etc.)
  • jobs: A set of jobs to execute
  • runs-on: The environment to run the job on (ubuntu-latest, windows-latest, macos-latest, etc.)
  • steps: A sequence of steps to execute within a job
  • uses: The action to use
  • with: Parameters to pass to the action
  • run: Commands to execute

Trigger Events for GitHub Actions

Pushes and Pull Requests

The most common triggers are pushes to specific branches or pull requests. You can also filter to run workflows only for specific branches or paths.

on:
  push:
    branches: [ main, develop ]
    paths:
      - 'src/**'
      - 'package.json'
  pull_request:
    branches: [ main ]

Scheduled Execution

You can use cron syntax to run workflows on a regular schedule. This is useful for regular backups or checking for dependency updates.

on:
  schedule:
    # Run at 3 AM (UTC) every day
    - cron: '0 3 * * *'

Manual Triggers

Using the workflow_dispatch event, you can manually run workflows from the GitHub web interface. You can also optionally define input parameters.

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Deployment environment'
        required: true
        default: 'staging'
        type: choice
        options:
          - staging
          - production

Other Events

GitHub Actions supports many GitHub events as triggers, including release creation, issue creation/updates, and discussion creation.

on:
  release:
    types: [published]
  issues:
    types: [opened, edited]

Jobs and Steps

Defining Jobs

Each job in a workflow runs in an independent execution environment. By default, jobs run in parallel, but you can define dependencies to run them sequentially.

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      # Build steps...
      
  test:
    needs: build
    runs-on: ubuntu-latest
    steps:
      # Test steps...
      
  deploy:
    needs: [build, test]
    runs-on: ubuntu-latest
    steps:
      # Deploy steps...

Matrix Builds

Using a matrix strategy, you can run the same job multiple times with different configurations (such as OS or runtime versions).

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [14.x, 16.x, 18.x]
    steps:
      - uses: actions/checkout@v3
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm install
      - run: npm test

Sharing Data Between Jobs

You can use artifacts to share files between jobs. This is useful when you need to use build artifacts in testing or deployment jobs.

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm install
      - run: npm run build
      - uses: actions/upload-artifact@v3
        with:
          name: build-files
          path: dist/
          
  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v3
        with:
          name: build-files
          path: dist/
      - run: ./deploy.sh

Using Actions

Using Published Actions

Many published actions are registered in the GitHub Marketplace. Using these actions makes it easy to implement common tasks.

Actions are referenced using the uses keyword:

steps:
  - uses: actions/checkout@v3
  - uses: actions/setup-node@v3
    with:
      node-version: '16'
  - uses: actions/cache@v3
    with:
      path: ~/.npm
      key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

Creating Custom Actions

You can create your own custom actions to meet specific needs. Actions can be implemented as JavaScript or Docker containers.

Example of a JavaScript action (action.yml):

name: 'Hello World'
description: 'An action that displays a greeting'
inputs:
  who-to-greet:
    description: 'Who to greet'
    required: true
    default: 'World'
outputs:
  time:
    description: 'The time when the greeting was made'
runs:
  using: 'node16'
  main: 'index.js'

Corresponding JavaScript file (index.js):

const core = require('@actions/core');

try {
  // Get input parameter
  const nameToGreet = core.getInput('who-to-greet');
  console.log(`Hello ${nameToGreet}!`);
  
  // Set output parameter
  const time = new Date().toTimeString();
  core.setOutput("time", time);
} catch (error) {
  core.setFailed(error.message);
}

Environment Variables and Secrets

Using Environment Variables

You can define environment variables in your workflow and share them between steps.

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      NODE_ENV: production
    steps:
      - uses: actions/checkout@v3
      - name: Display environment variables
        run: echo "NODE_ENV is $NODE_ENV"
      - name: Step-level environment variables
        env:
          DEBUG: true
        run: echo "DEBUG is $DEBUG"

Managing Secrets

Sensitive information such as API keys and passwords can be stored as GitHub repository secrets and used safely within your workflows.

How to set up secrets:

  1. Open the "Settings" tab of your GitHub repository
  2. Select "Secrets and variables" → "Actions" from the left menu
  3. Click the "New repository secret" button
  4. Enter the name and value of the secret and save

Using secrets in workflows:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1

Conditional Execution

If Conditions

You can use if conditions to run jobs or steps only when specific conditions are met.

jobs:
  deploy-to-production:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      # Deploy steps...
      
  notify:
    runs-on: ubuntu-latest
    steps:
      - name: Success notification
        if: success()
        run: ./notify-success.sh
        
      - name: Failure notification
        if: failure()
        run: ./notify-failure.sh

Expressions and Functions

GitHub Actions provides many functions and operators that can be used in conditional expressions or for generating values.

steps:
  - name: Process based on branch name
    if: contains(github.ref, 'feature/')
    run: echo "This is a feature branch"
    
  - name: Set environment variable
    run: echo "TIMESTAMP=$(date +%s)" >> $GITHUB_ENV
    
  - name: Use environment variable
    run: echo "Current timestamp is ${{ env.TIMESTAMP }}"

Advanced Usage Examples of GitHub Actions

Complex CI/CD Pipeline

You can build a complete CI/CD pipeline including build, test, and deployment by combining multiple jobs.

name: CI/CD Pipeline

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main, develop ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '16'
      - name: Install dependencies
        run: npm ci
      - name: Build
        run: npm run build
      - name: Upload build artifacts
        uses: actions/upload-artifact@v3
        with:
          name: build-files
          path: dist/

  test:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '16'
      - name: Install dependencies
        run: npm ci
      - name: Run tests
        run: npm test

  deploy-staging:
    if: github.ref == 'refs/heads/develop'
    needs: [build, test]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Download build artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-files
          path: dist/
      - name: Deploy to staging
        run: ./deploy-staging.sh

  deploy-production:
    if: github.ref == 'refs/heads/main'
    needs: [build, test]
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v3
      - name: Download build artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-files
          path: dist/
      - name: Deploy to production
        run: ./deploy-production.sh

GitHub Actions Best Practices

Workflow Optimization

  • Cache dependencies to reduce build time
  • Set conditions to only run necessary jobs
  • Split large workflows into multiple smaller workflows
  • Utilize matrix builds to parallelize tests

Security Measures

  • Store sensitive information as secrets and don't write them directly in workflow files
  • When using third-party actions, choose ones from trusted sources and pin their versions
  • Limit access to sensitive information in workflows triggered by pull requests
  • Set GITHUB_TOKEN permissions to the minimum necessary

Improving Maintainability

  • Separate complex commands into script files
  • Implement common steps as reusable actions
  • Add appropriate comments to workflow files
  • Regularly review workflow execution results and optimize them

Summary

GitHub Actions is a powerful workflow automation tool directly integrated with GitHub repositories. It can automatically execute a series of processes such as building, testing, and deploying, triggered by events like code pushes or pull requests.

By leveraging features such as reusable actions, matrix builds, and self-hosted runners, you can build efficient and flexible CI/CD pipelines. Additionally, you can easily extend your development workflows by using the numerous actions published in the GitHub Marketplace.

By implementing GitHub Actions, development teams can automate manual testing and deployment tasks, enabling faster software releases while improving code quality.

Git Fork

Git Fork is the process of creating a copy of another developer's repository in your own account. By forking, you can make changes to a project freely without affecting the original repository. This is an essential feature for contributing to open-source projects and collaborative development within organizations.

After making changes to a forked repository, you can propose those changes to the original repository by creating a Pull Request (or Merge Request). This allows the project maintainers to review your changes and merge them into the original repository if appropriate.

Basic Concepts of Forking

Difference Between Fork and Clone

In Git terminology, "fork" and "clone" are similar but distinct concepts:

  • Fork: A server-side operation that creates a copy of another user's repository in your account. Forking is primarily a feature of Git hosting services like GitHub and GitLab.
  • Clone: An operation that creates a copy of a remote repository on your local machine. This is done using the git clone command.

In a typical workflow, you first fork a repository and then clone your fork to work on it locally.

Main Uses of Forks

Forks are primarily used for the following purposes:

  • Contributing to open-source projects
  • Starting new projects based on existing ones
  • Collaborative development within organizations (especially when access permissions are restricted)
  • Developing experimental changes or features

How to Fork Repositories

Forking on GitHub

The process of forking a repository on GitHub is very simple:

  1. Navigate to the repository page you want to fork.
  2. Click the "Fork" button in the top-right corner of the page.
  3. Select the destination organization if needed.
  4. Click the "Create fork" button.

Once the fork is complete, a copy of the original repository will be created in your account. The URL of this repository will typically be https://github.com/your-username/repository-name.

Forking on GitLab

The process for forking a repository on GitLab is similar:

  1. Navigate to the project page you want to fork.
  2. Click the "Fork" button in the top-right corner of the page.
  3. Select the namespace (user or group) where you want to fork the project.
  4. Modify the project name and other settings if needed.
  5. Click the "Fork project" button.

Working with Forked Repositories

Cloning Your Fork and Setting Up Remotes

To work with your forked repository locally, first create a clone:

git clone https://github.com/your-username/repository-name.git
cd repository-name

To make it easier to sync with the original repository (upstream repository), it's recommended to add an "upstream" remote:

git remote add upstream https://github.com/original-owner/repository-name.git

To verify that the remotes are set up correctly:

git remote -v

This should display something like:

origin    https://github.com/your-username/repository-name.git (fetch)
origin    https://github.com/your-username/repository-name.git (push)
upstream  https://github.com/original-owner/repository-name.git (fetch)
upstream  https://github.com/original-owner/repository-name.git (push)

Syncing with the Upstream Repository

To incorporate changes from the original repository (upstream repository) into your fork, follow these steps:

# Fetch the latest changes from the upstream repository
git fetch upstream

# Switch to your local main branch
git checkout main

# Merge the changes from the upstream repository into your local main branch
git merge upstream/main

# Push the changes to your fork
git push origin main

This keeps your fork synchronized with the original repository and up to date.

Creating and Proposing Changes

The typical workflow for making changes in a forked repository and proposing them to the original repository is:

  1. Sync your fork with the upstream repository.
  2. Create a new feature branch:
    git checkout -b feature/new-feature-name
  3. Make changes and commit them:
    git add .
    git commit -m "Description of changes"
  4. Push the changes to your fork:
    git push origin feature/new-feature-name
  5. Create a pull request (or merge request) to the original repository using the GitHub or GitLab web interface.

Creating and Managing Pull Requests

Creating a Pull Request on GitHub

The steps to create a pull request on GitHub are:

  1. Navigate to your forked repository page.
  2. Click the "Pull requests" tab.
  3. Click the "New pull request" button.
  4. Select the base repository (original repository) and branch, and the compare repository (your fork) and branch.
  5. Review the changes and click the "Create pull request" button.
  6. Enter a title and description for your pull request.
  7. Click the "Create pull request" button to finalize.

Pull Request Best Practices

Best practices for creating effective pull requests include:

  • Clear title and description: Concisely explain what changes you've made and why they're necessary.
  • Break down large changes: Divide large changes into multiple smaller pull requests to make review easier.
  • Add tests: When possible, include tests for your changes.
  • Follow coding conventions: Adhere to the project's coding conventions and style guides.
  • Respond to review comments: Respond promptly and courteously to feedback from reviewers.

Making Changes After a Pull Request

If additional changes are needed after submitting a pull request, simply commit and push to the same branch:

git add .
git commit -m "Address review feedback"
git push origin feature/new-feature-name

These changes will automatically be added to the existing pull request.

Managing and Maintaining Forks

Regular Synchronization with Upstream

When using a fork over an extended period, it's important to synchronize regularly with the upstream repository. This minimizes conflicts and allows you to incorporate the latest features and bug fixes.

The frequency of synchronization depends on how active the upstream repository is, but it's recommended to always sync before making new changes.

Handling Forks That Are No Longer Needed

When you've completed your contributions to a project and no longer need the fork, you have several options:

  • Keep it: You can retain the fork if you might contribute again in the future.
  • Archive it: On GitHub and GitLab, you can archive a repository to make it read-only.
  • Delete it: If completely unnecessary, you can delete the fork. Note that this action cannot be undone.

Advanced Usage of Forks

Contributing to Other Forks

It's also possible to contribute to someone else's fork. This is useful when multiple developers are collaborating to propose a significant change to the original repository.

In this case, you can add their fork as a remote and pull from or push to it:

git remote add collaborator https://github.com/collaborator-username/repository-name.git
git fetch collaborator
git checkout -b feature/collaborative-feature collaborator/feature/collaborative-feature
# Make changes
git push collaborator feature/collaborative-feature

Using Forks for Experimentation

Forks are ideal for trying experimental changes without affecting the original project. For example, you can test new technologies or approaches, or perform large-scale refactoring.

If the experiment is successful, you can propose the changes to the original repository. If it fails, there's no impact on the original project.

Common Problems and Solutions

Resolving Merge Conflicts

Merge conflicts can occur when syncing with the upstream repository or when creating a pull request. This happens when the same part of a file has been changed in different ways.

To resolve merge conflicts:

  1. Open the files with conflicts.
  2. Look for conflict markers (<<<<<<<, =======, >>>>>>>).
  3. Edit the code appropriately to integrate both changes or choose one over the other.
  4. Remove the conflict markers.
  5. Stage and commit the changes:
    git add .
    git commit -m "Resolve merge conflicts"

When a Fork Becomes Outdated

Forks that haven't been synchronized for a long time can fall significantly behind the upstream repository. In this case, you can:

  • Rebase: Rebase your changes on top of the upstream changes.
    git fetch upstream
    git rebase upstream/main
  • Re-create the fork: In extreme cases, it might be easier to delete the fork and create a new one.

Summary

Git Fork is an essential feature for contributing to open-source projects and collaborative development. By using forks, you can contribute to projects even without direct access to the original repository, or start new projects based on existing code.

Effective use of forks involves regular synchronization with the upstream repository, proper branch management, and creating clear pull requests. By following these practices, you can enable smooth collaborative development and effectively contribute to open-source communities and team development.

Forking is not just a technical feature but also a social tool that enables distributed collaborative development. It allows developers from around the world to collaborate beyond geographical constraints and create better software together.