diff --git a/app/api/partitions.py b/app/api/partitions.py
index 5d7f5642139e3cded34c9e978d0aa02d2864d72b..207fa9ec45fcc4544383e3f115fd6bfd236ff595 100644
--- a/app/api/partitions.py
+++ b/app/api/partitions.py
@@ -220,20 +220,9 @@ def group_remove_etud(group_id: int, etudid: int):
     group = query.first_or_404()
     if not group.partition.formsemestre.etat:
         return json_error(403, "formsemestre verrouillé")
-    if etud in group.etuds:
-        group.etuds.remove(etud)
-        db.session.commit()
-        Scolog.logdb(
-            method="group_remove_etud",
-            etudid=etud.id,
-            msg=f"Retrait du groupe {group.group_name} de {group.partition.partition_name}",
-            commit=True,
-        )
-        # Update parcours
-        group.partition.formsemestre.update_inscriptions_parcours_from_groups(
-            etudid=etudid
-        )
-        sco_cache.invalidate_formsemestre(group.partition.formsemestre_id)
+
+    group.remove_etud(etud)
+
     return {"group_id": group_id, "etudid": etudid}
 
 
diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py
index 677bfb1789ae1deb37bd13e35a50f7a094808769..20a1cf359e450035a361c5ca2c5588b6f88c667c 100644
--- a/app/models/formsemestre.py
+++ b/app/models/formsemestre.py
@@ -841,7 +841,7 @@ class FormSemestre(db.Model):
         Les groupes de parcours sont ceux de la partition scu.PARTITION_PARCOURS
         et leur nom est le code du parcours (eg "Cyber").
 
-        Si etudid est sépcifié, n'affecte que cet étudiant,
+        Si etudid est spécifié, n'affecte que cet étudiant,
         sinon traite tous les inscrits du semestre.
         """
         if self.formation.referentiel_competence_id is None:
diff --git a/app/models/groups.py b/app/models/groups.py
index f2982cf4215f8db8f7a50dc3315ee87298e605db..b8fb5f46dc2edf5da1d91379141b59d6cff87c1e 100644
--- a/app/models/groups.py
+++ b/app/models/groups.py
@@ -11,8 +11,8 @@ from operator import attrgetter
 from sqlalchemy.exc import IntegrityError
 
 from app import db, log
-from app.models import SHORT_STR_LEN
-from app.models import GROUPNAME_STR_LEN
+from app.models import Scolog, GROUPNAME_STR_LEN, SHORT_STR_LEN
+from app.scodoc import sco_cache
 from app.scodoc import sco_utils as scu
 from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
 
@@ -83,6 +83,14 @@ class Partition(db.Model):
             return False
         return True
 
+    @classmethod
+    def formsemestre_remove_etud(cls, formsemestre_id: int, etud: "Identite"):
+        "retire l'étudiant de toutes les partitions de ce semestre"
+        for group in GroupDescr.query.join(Partition).filter_by(
+            formsemestre_id=formsemestre_id
+        ):
+            group.remove_etud(etud)
+
     def is_parcours(self) -> bool:
         "Vrai s'il s'agit de la partition de parcours"
         return self.partition_name == scu.PARTITION_PARCOURS
@@ -248,6 +256,24 @@ class GroupDescr(db.Model):
             return False
         return True
 
+    def remove_etud(self, etud: "Identite"):
+        "Enlève l'étudiant de ce groupe s'il en fait partie (ne fait rien sinon)"
+        if etud in self.etuds:
+            self.etuds.remove(etud)
+            db.session.commit()
+            Scolog.logdb(
+                method="group_remove_etud",
+                etudid=etud.id,
+                msg=f"Retrait du groupe {self.group_name} de {self.partition.partition_name}",
+                commit=True,
+            )
+            # Update parcours
+            if self.partition.partition_name == scu.PARTITION_PARCOURS:
+                self.partition.formsemestre.update_inscriptions_parcours_from_groups(
+                    etudid=etud.id
+                )
+            sco_cache.invalidate_formsemestre(self.partition.formsemestre_id)
+
 
 group_membership = db.Table(
     "group_membership",
diff --git a/app/scodoc/sco_formsemestre_inscriptions.py b/app/scodoc/sco_formsemestre_inscriptions.py
index 24943558ee0af6377f95fc24bcc429b9f4be511c..282b51957bf79072f0f857c57c1d25bbbe1cd6d2 100644
--- a/app/scodoc/sco_formsemestre_inscriptions.py
+++ b/app/scodoc/sco_formsemestre_inscriptions.py
@@ -38,7 +38,7 @@ from app.comp import res_sem
 from app.comp.res_compat import NotesTableCompat
 from app.models import Formation, FormSemestre, FormSemestreInscription, Scolog
 from app.models.etudiants import Identite
-from app.models.groups import GroupDescr
+from app.models.groups import Partition, GroupDescr
 from app.models.validations import ScolarEvent
 import app.scodoc.sco_utils as scu
 from app import log
@@ -236,6 +236,10 @@ def do_formsemestre_desinscription(etudid, formsemestre_id):
         sco_moduleimpl.do_moduleimpl_inscription_delete(
             moduleimpl_inscription_id, formsemestre_id=formsemestre_id
         )
+
+    # -- désincription de tous les groupes des partitions de ce semestre
+    Partition.formsemestre_remove_etud(formsemestre_id, etud)
+
     # -- désincription du semestre
     do_formsemestre_inscription_delete(
         insem["formsemestre_inscription_id"], formsemestre_id=formsemestre_id
@@ -259,7 +263,7 @@ def do_formsemestre_desinscription(etudid, formsemestre_id):
         cnx,
         method="formsemestre_desinscription",
         etudid=etudid,
-        msg="desinscription semestre %s" % formsemestre_id,
+        msg=f"desinscription semestre {formsemestre_id}",
         commit=False,
     )
 
diff --git a/app/scodoc/sco_inscr_passage.py b/app/scodoc/sco_inscr_passage.py
index 68d838b5ad7e7f0e8ff865e0b28447b640079230..5a44ddbd7b49597ae6f1ba1725814255928efb9a 100644
--- a/app/scodoc/sco_inscr_passage.py
+++ b/app/scodoc/sco_inscr_passage.py
@@ -171,12 +171,16 @@ def list_inscrits_date(sem):
     return [x[0] for x in cursor.fetchall()]
 
 
-def do_inscrit(sem, etudids, inscrit_groupes=False):
+def do_inscrit(sem, etudids, inscrit_groupes=False, inscrit_parcours=False):
     """Inscrit ces etudiants dans ce semestre
     (la liste doit avoir été vérifiée au préalable)
-    En option: inscrit aux mêmes groupes que dans le semestre origine
+    En option:
+    - Si inscrit_groupes, inscrit aux mêmes groupes que dans le semestre origine
+        (toutes partitions, y compris parcours)
+    - Si inscrit_parcours, inscrit au même groupe de parcours (mais ignore les autres partitions)
+    (si les deux sont vrais, inscrit_parcours n'a pas d'effet)
     """
-    # TODO à ré-écrire pour utiliser le smodèle, notamment GroupDescr
+    # TODO à ré-écrire pour utiliser les modèles, notamment GroupDescr
     formsemestre: FormSemestre = db.session.get(FormSemestre, sem["formsemestre_id"])
     formsemestre.setup_parcours_groups()
     log(f"do_inscrit (inscrit_groupes={inscrit_groupes}): {etudids}")
@@ -187,7 +191,7 @@ def do_inscrit(sem, etudids, inscrit_groupes=False):
             etat=scu.INSCRIT,
             method="formsemestre_inscr_passage",
         )
-        if inscrit_groupes:
+        if inscrit_groupes or inscrit_parcours:
             # Inscription dans les mêmes groupes que ceux du semestre  d'origine,
             # s'ils existent.
             # (mise en correspondance à partir du nom du groupe, sans tenir compte
@@ -223,11 +227,16 @@ def do_inscrit(sem, etudids, inscrit_groupes=False):
                 group: GroupDescr = db.session.get(
                     GroupDescr, partition_group["group_id"]
                 )
-                sco_groups.change_etud_group_in_partition(etudid, group)
+                if inscrit_groupes or (
+                    group.partition.partition_name == scu.PARTITION_PARCOURS
+                    and inscrit_parcours
+                ):
+                    sco_groups.change_etud_group_in_partition(etudid, group)
 
 
-def do_desinscrit(sem, etudids):
-    log("do_desinscrit: %s" % etudids)
+def do_desinscrit(sem: dict, etudids: list[int]):
+    "désinscrit les étudiants indiqués du formsemestre"
+    log(f"do_desinscrit: {etudids}")
     for etudid in etudids:
         sco_formsemestre_inscriptions.do_formsemestre_desinscription(
             etudid, sem["formsemestre_id"]
@@ -273,6 +282,7 @@ def formsemestre_inscr_passage(
     formsemestre_id,
     etuds=[],
     inscrit_groupes=False,
+    inscrit_parcours=False,
     submitted=False,
     dialog_confirmed=False,
     ignore_jury=False,
@@ -291,6 +301,7 @@ def formsemestre_inscr_passage(
 
     """
     inscrit_groupes = int(inscrit_groupes)
+    inscrit_parcours = int(inscrit_parcours)
     ignore_jury = int(ignore_jury)
     sem = sco_formsemestre.get_formsemestre(formsemestre_id)
     # -- check lock
@@ -335,6 +346,7 @@ def formsemestre_inscr_passage(
             candidats_non_inscrits,
             inscrits_ailleurs,
             inscrit_groupes=inscrit_groupes,
+            inscrit_parcours=inscrit_parcours,
             ignore_jury=ignore_jury,
         )
     else:
@@ -376,6 +388,7 @@ def formsemestre_inscr_passage(
                         "formsemestre_id": formsemestre_id,
                         "etuds": ",".join([str(x) for x in etuds]),
                         "inscrit_groupes": inscrit_groupes,
+                        "inscrit_parcours": inscrit_parcours,
                         "ignore_jury": ignore_jury,
                         "submitted": 1,
                     },
@@ -388,6 +401,7 @@ def formsemestre_inscr_passage(
                     sem,
                     a_inscrire,
                     inscrit_groupes=inscrit_groupes,
+                    inscrit_parcours=inscrit_parcours,
                 )
                 # Désinscriptions:
                 do_desinscrit(sem, a_desinscrire)
@@ -433,15 +447,21 @@ def _build_page(
     candidats_non_inscrits,
     inscrits_ailleurs,
     inscrit_groupes=False,
+    inscrit_parcours=False,
     ignore_jury=False,
 ):
     formsemestre: FormSemestre = db.session.get(FormSemestre, sem["formsemestre_id"])
     inscrit_groupes = int(inscrit_groupes)
+    inscrit_parcours = int(inscrit_parcours)
     ignore_jury = int(ignore_jury)
     if inscrit_groupes:
         inscrit_groupes_checked = " checked"
     else:
         inscrit_groupes_checked = ""
+    if inscrit_parcours:
+        inscrit_parcours_checked = " checked"
+    else:
+        inscrit_parcours_checked = ""
     if ignore_jury:
         ignore_jury_checked = " checked"
     else:
@@ -458,17 +478,23 @@ def _build_page(
         &nbsp;<a href="#help">aide</a>
 
         <input name="inscrit_groupes" type="checkbox" value="1"
-            {inscrit_groupes_checked}>inscrire aux mêmes groupes</input>
+            {inscrit_groupes_checked}>inscrire aux mêmes groupes (y compris parcours)</input>
+
+        <input name="inscrit_parcours" type="checkbox" value="1"
+            {inscrit_parcours_checked}>inscrire aux mêmes parcours</input>
 
         <input name="ignore_jury" type="checkbox" value="1" onchange="document.f.submit()"
             {ignore_jury_checked}>inclure tous les étudiants (même sans décision de jury)</input>
 
-        <div class="pas_recap">Actuellement <span id="nbinscrits">{len(inscrits)}</span> inscrits
-        et {len(candidats_non_inscrits)} candidats supplémentaires
+        <div class="pas_recap">Actuellement <span id="nbinscrits">{len(inscrits)}</span>
+        inscrits et {len(candidats_non_inscrits)} candidats supplémentaires.
         </div>
 
-        <div>{scu.EMO_WARNING} <em>Seuls les semestres dont la date de fin est antérieure à la date de début
-        de ce semestre ({formsemestre.date_debut.strftime("%d/%m/%Y")}) sont pris en compte.</em></div>
+        <div>{scu.EMO_WARNING}
+        <em>Seuls les semestres dont la date de fin est antérieure à la date de début
+        de ce semestre ({formsemestre.date_debut.strftime("%d/%m/%Y")}) sont pris en
+        compte.</em>
+        </div>
         {etuds_select_boxes(auth_etuds_by_sem, inscrits_ailleurs)}
 
         <input type="submit" name="submitted" value="Appliquer les modifications"/>
@@ -498,7 +524,8 @@ def _build_page(
     return H
 
 
-def formsemestre_inscr_passage_help(sem):
+def formsemestre_inscr_passage_help(sem: dict):
+    "texte d'aide en bas  de la page passage des étudiants"
     return f"""<div class="pas_help"><h3><a name="help">Explications</a></h3>
     <p>Cette page permet d'inscrire des étudiants dans le semestre destination
     <a class="stdlink"
@@ -507,18 +534,34 @@ def formsemestre_inscr_passage_help(sem):
     }">{sem['titreannee']}</a>,
     et d'en désincrire si besoin.
     </p>
-    <p>Les étudiants sont groupés par semestres d'origines. Ceux qui sont en caractères
+    <p>Les étudiants sont groupés par semestre d'origine. Ceux qui sont en caractères
     <span class="inscrit">gras</span> sont déjà inscrits dans le semestre destination.
     Ceux qui sont en <span class"inscrailleurs">gras et en rouge</span> sont inscrits
-    dans un <em>autre</em> semestre.</p>
-    <p>Au départ, les étudiants déjà inscrits sont sélectionnés; vous pouvez ajouter d'autres
-    étudiants à inscrire dans le semestre destination.</p>
-    <p>Si vous dé-selectionnez un étudiant déjà inscrit (en gras), il sera désinscrit.</p>
-    <p>Le bouton <em>inscrire aux mêmes groupes</em> ne prend en compte que les groupes qui existent 
-    dans les deux semestres: pensez à créer les partitions et groupes que vous souhaitez conserver
-    <b>avant</b> d'inscrire les étudiants.
+    dans un <em>autre</em> semestre.
+    </p>
+    <p>Au départ, les étudiants déjà inscrits sont sélectionnés; vous pouvez ajouter
+    d'autres étudiants à inscrire dans le semestre destination.
+    </p>
+
+    <p>Si vous dé-selectionnez un étudiant déjà inscrit (en gras), il sera désinscrit.
+    </p>
+
+    <p>Le bouton <em>inscrire aux mêmes groupes</em> ne prend en compte que les groupes
+    qui existent dans les deux semestres: pensez à créer les partitions et groupes que
+    vous souhaitez conserver <b>avant</b> d'inscrire les étudiants.
+    </p>
+
+    <p>Les parcours de BUT sont gérés comme des groupes de la partition parcours: si on
+    conserve les groupes, on conserve les parcours (là aussi, pensez à les cocher dans
+    <a class="stdlink" href="{
+        url_for("notes.formsemestre_editwithmodules", scodoc_dept=g.scodoc_dept,
+                formsemestre_id=sem["formsemestre_id"] )
+    }">modifier le semestre</a> avant de faire passer les étudiants).
+    </a>
+
+    <p class="help">Aucune action ne sera effectuée si vous n'appuyez pas sur le bouton
+    "Appliquer les modifications" !
     </p>
-    <p class="help">Aucune action ne sera effectuée si vous n'appuyez pas sur le bouton "Appliquer les modifications" !</p>
     </div>
     """