Skip to content

Assignment1 with Task1 and Task2

GregoAV/Assignment1

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Git Workflow Strategy Documentation - Task 2

This repository demonstrates advanced Git operations as part of Assignment 2, following a Git Flow–like branching model.
The purpose is to practice merge, rebase, squash, and cherry-pick commands while managing conflicts and maintaining a clean project history.

The documentation branch is used exclusively for recording the workflow, describing branch purposes, and summarizing the strategy used in this assignment as required by the rubric.


Initial Branch Structure and Purpose

All feature branches and the documentation branch originate from the main development branch (dev).

Branch Source Branch Purpose Description of Contents
main Production / Stable Contains the initial, working version of the Number Guessing Game. Will only receive changes from dev after testing and integration are complete.
dev main Integration / Staging Central branch where all features are merged, rebased, and tested before being pushed to main.
documentation dev Documentation Records the structure, workflow, and conflict resolutions. Includes this README file.
feature1 dev Merge Practice Adds a quit-game option and replay loop. This branch will be integrated into dev using a standard merge (Steps 2 & 3).
feature2 dev Rebase Practice Implements a maximum attempts feature and an encouraging message. It will be integrated into dev using rebase (Steps 4 & 6).
feature3 dev Squash Practice Adds a hint system that tells the player if their guess is close. Multiple commits will be squashed into one before merging into dev (Step 5).
hotfix main Cherry-Pick Practice Fixes the random number generation to correctly include the upper bound. This change will be cherry-picked to main and then merged back into dev (Step 7).

Summary of Workflow Strategy

  1. Start from dev to create the documentation branch.
  2. Merge feature1 into dev (merge strategy).
  3. Rebase feature2 onto dev, resolving conflicts as needed.
  4. Squash multiple commits from feature3 into one and merge it into dev.
  5. Cherry-pick the hotfix commit to main and propagate it back to dev.
  6. Confirm that all tests pass on dev and finalize documentation.

Workflow Log

Step 2 & 3: Merge dev into feature1 and then feature1 into dev

Strategy:
A standard Git merge was used to integrate the work from feature1 into the integration branch, dev. This process included first updating the feature branch by merging the latest changes from dev (git merge dev while on feature1), and then merging the updated branch back into dev.

Conflict Resolution:
A conflict occurred in Main.java between a version comment introduced in feature1 and a new print statement added in dev.
Resolution: The conflict markers were manually removed, and both lines of code were kept to preserve all intended functionality. The final merged version reflects the combined updates from both branches.

Cleanup:
After verifying the merge was successful, the feature1 branch was deleted locally using git branch -d feature1 to maintain a clean and organized branch structure.

Verification: All tests passed successfully after each merge stage.

  • When merging dev into feature1, the build completed without errors after fixing the conflict in Main.java, and all feature tests passed.
  • The subsequent merge of feature1 back into dev was completed as a fast-forward merge, confirming that no additional conflicts were introduced. Both merges were validated through successful test execution on the dev branch, ensuring that the integration remained stable.

Step 4: Rebase feature2 onto dev

Strategy:
The feature2 branch was updated using a git rebase dev operation instead of a standard merge. This approach ensured a clean, linear commit history, stacking feature2’s commits directly on top of the latest dev branch. It also allowed resolving conflicts in an ordered, step-by-step manner while preserving both branches’ logic.

Conflict Resolution:
The rebase process encountered two sequential conflict stops caused by overlapping logic between the updated dev branch and feature2.

  • Resolution Details:
    • Stop 1 (Commit 45aa640):
      Conflict in GameEngine.java in makeGuess(int guess) method between the userQuit functionality from dev and the new gameOver / MAX_ATTEMPTS logic introduced in feature2.
      The resolution combined both behaviors by keeping both fields and ensuring that userQuit handled exit conditions while gameOver controlled the attempt limit. A missing closing brace (}) was also added in hasUserQuit() method.
    • Stop 2 (Commit e367776):
      Conflicts occurred across three files and required simultaneous integration:
      1. GameEngine.java – Merged the makeGuess method logic for gameOver with the userQuit handling. Fixed a missing closing brace.
      2. GameUI.java – Integrated both loop conditions: while (!engine.isGameWon() && !engine.isGameOver()) and !engine.hasUserQuit(). Added a missing closing brace.
      3. GameEngineTest.java – Merged test cases for testQuitWithNegativeNumber (from dev) with new tests such as testMaxAttemptsReached and testRemainingAttemptsDisplayed. Added a missing closing brace in testQuitDoesNotIncrementAttempts.
    • After each conflict set was fixed, the changes were staged (git add <filename>) and the process continued using git rebase --continue until all commits were successfully applied.

Verification:
Both intermediate and final builds compiled without errors after each conflict resolution.
All existing and new unit tests passed successfully, confirming that:

  • The feature2 logic for maximum attempts and game-over state was correctly integrated.
  • The feature1 quit-game functionality remained intact.
  • The final rebase history was linear and clean on dev, with no merge commits introduced.

Step 5: Squash and Merge feature3 into dev

Strategy:
The feature3 branch was refined using an interactive rebase (git rebase -i) to consolidate multiple small incremental commits into a single, meaningful commit. This approach ensured a cleaner, more readable project history by grouping related changes together.

Squash Process:

  • Interactive Rebase: Four commits (started hint, got it done, had to fix, done) were combined into one by keeping the first commit as pick and marking the following three as squash.
  • Consolidated Commit Message: The combined commit message was rewritten as "Add hint system to show proximity after 3 attempts", clearly summarizing the feature.
  • Post-Squash Rebase: After squashing, a git rebase dev was executed to align feature3 on top of the latest dev history before integration.

Conflict Resolution during Rebase:
A single rebase conflict occurred across two files — GameEngine.java and GameEngineTest.java.

  • Resolution:
    • In GameEngine.java, the hintsEnabled logic introduced in feature3 conflicted with the features from dev.
      The resolution involved merging all behaviors together within the makeGuess() method to ensure correct handling of hint generation.
    • In GameEngineTest.java, the hint-related test cases (testHintVeryClose, testHintGettingWarmer, etc.) conflicted with the quit-game tests. The conflict was resolved by integrating both sets of tests and adding the missing closing brace (}) in testQuitDoesNotIncrementAttempts.

After resolving each conflict, changes were staged with git add <filename> and the rebase process continued using git rebase --continue until all commits were successfully applied.

Integration:
Once rebasing was complete, the squashed feature3 branch was merged into dev using a Fast-Forward Merge, preserving a clean and linear history without introducing additional merge commits.

Verification:
The project compiled successfully, and all unit tests passed — including the newly added hint feature tests and the existing tests — confirming a stable and complete integration of all functionalities.

Cleanup:
After verifying a successful integration, the feature3 branch was keep locally for reference.

Step 6: Update feature2 and Final Merge into dev

Strategy:
The final integration of feature2 ensured that all recent changes from dev—including feature1’s quit logic and feature3’s squashed hint feature—were properly synchronized before completing its final merge. This step guaranteed that all feature sets coexisted without conflicts in the unified development branch.

Synchronization and Conflict Resolution:

  • The update (git merge dev into feature2) produced merge conflicts in two key files:
    • GameEngine.java
    • GameEngineTest.java
  • Resolution:
    • In GameEngine.java, the feature2 logic (gameOver and MAX_ATTEMPTS) conflicted with the feature3 logic (hintsEnabled and hint generation). The solution required integrating all functionalities into a single, consistent implementation of makeGuess(int guess), ensuring proper handling of quitting, hint display, and attempt tracking.
    • In GameEngineTest.java, overlapping tests for max attempts and hint-related behaviors required manual merging. The conflict was resolved by preserving both sets of tests and correcting one missing closing brace (}) in testResetClearsGameOver() method.
    • All conflict markers were removed, the code was verified to compile successfully, and changes were committed to finalize the merge on feature2.

Integration:
After conflict resolution, the updated feature2 branch was merged into dev using a Fast-Forward Merge, resulting in a clean, linear history without an additional merge commit.

Verification:
The project compiled successfully, and all unit tests passed—including those for quit logic, maximum attempts, and hint behavior—confirming that the three distinct feature sets were no Cleanup:
After verifying a successful integration, the feature2 branch was keep locally for reference.

Step 7: Hotfix Integration and Propagation (Cherry-Pick Practice)

Objective:
To simulate an urgent production fix (hotfix) and practice propagating a pre-existing fix to the main and dev branches, ensuring both remain synchronized.

Hotfix Identification and Cherry-Pick (on main):

  • The hotfix branch contained the commit “Fix randomInt to properly include max value in range” (ab7cd7b), which corrected the range logic in Utils.java and added new test coverage in UtilsTest.java.
  • A successful git cherry-pick hotfix was executed on the main branch, integrating the fix and the test file into the production branch.
  • Observation: A subsequent attempt to reapply the same commit using its hash (git cherry-pick ab7cd7b) triggered an “empty commit” warning — confirming the hotfix had already been applied successfully in the first attempt.

Propagation to dev (Merge):

  • The applied fix was then propagated to the development branch by performing git merge main on dev.
  • This merge completed cleanly with no conflicts, confirming successful synchronization between the production and development branches.

Verification:

  • The merge output showed the expected updates in Utils.java and the addition of UtilsTest.java.
  • All unit tests passed, verifying that the hotfix integrated properly alongside existing feature branches (feature1, feature2, and feature3).

Cleanup:

  • Since the hotfix branch was already merged and all changes were synchronized, no additional cleanup was required.

Step 8: Final Summary and Reflection

Overview:
This Git workflow successfully demonstrated a complete multi-branch development process involving merges, rebases, squashes, and cherry-picks.
Each strategy was applied in a realistic scenario to simulate collaborative software development and conflict resolution while maintaining a clean and traceable history.


Differences Between Merge, Rebase, Squash, and Cherry-Pick

Strategy Description Effect on History Typical Use Case
Merge Combines changes from one branch into another by creating a merge commit. Creates a non-linear history that preserves the original context of both branches. When collaboration is frequent and preserving the full branch history is important (e.g., merging feature branches into dev).
Rebase Moves or reapplies commits from one branch onto another base branch. Rewrites commit history to create a clean, linear timeline. When you want to integrate the latest changes before merging, or when maintaining a cleaner project history.
Squash Consolidates multiple commits into one single commit before merging. Produces a minimal, cleaner history representing a complete feature as one commit. When a feature branch has many small “work-in-progress” commits that should appear as one logical change.
Cherry-Pick Copies a specific commit from one branch and applies it to another. Adds a duplicate commit (new hash) containing the same changes. When you need to propagate an urgent fix (e.g., hotfix) to multiple branches without merging everything.

Observations in Git History

  • Feature1 (Merge):
    Merging preserved the original commit history, showing both the feature commits and the merge commit itself. This reflects a typical integration pattern where history transparency is prioritized.
  • Feature2 (Rebase):
    Rebasing provided a linear history, stacking the commits on top of the latest dev changes and removing intermediate merge commits. This made the timeline cleaner and easier to read.
  • Feature3 (Squash):
    After squashing, only one commit represented the entire feature, providing a concise and professional commit history that would be ideal for production logs.
  • Hotfix (Cherry-Pick):
    The single commit from the hotfix branch was applied directly to main and then propagated to dev, demonstrating selective integration of urgent fixes without merging unrelated work.

When to Use Each Strategy in Real Projects

  • Merge:
    Best for integrating collaborative work where multiple developers contribute to the same branch. It preserves context and avoids rewriting shared history.
  • Rebase:
    Useful for local, personal branches before merging into shared branches. It keeps the history linear and clean but should be avoided on public/shared branches to prevent confusion.
  • Squash:
    Ideal before merging a long-running feature branch into dev or main, as it condenses noisy intermediate commits into a single, meaningful one.
  • Cherry-Pick:
    Appropriate when a critical bug fix or small improvement from another branch needs to be applied selectively without merging the entire branch.

Verification and Final Outcome

All merges, rebases, and cherry-picks were completed successfully with manual conflict resolutions where needed.
After each integration step, all tests passed, confirming that the dev branch now contains:

  • The Quit feature (feature1)
  • The Max Attempts/Game Over feature (feature2)
  • The Hint System feature (feature3)
  • The Random Number Hotfix

Conclusion:
The final dev branch represents a clean, stable, and production-ready state.
Through this assignment, multiple Git integration strategies were practiced in a realistic workflow, demonstrating proficiency in managing complex branching scenarios, conflict handling, and maintaining an organized project history.

About

Assignment1 with Task1 and Task2

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages